Пример #1
0
 def start(self):
     if ServerConfig.enable_bonjour:
         application_map = dict((item.split(':')) for item in ServerConfig.application_map)
         for uri, app in application_map.iteritems():
             if app == 'echo':
                 service = BonjourService(service='sipuri', name='Echo Test', uri_user=uri, is_focus=False)
                 service.start()
                 service.presence_state = BonjourPresenceState('available', u'Call me to test your client')
                 self.bonjour_services.add(service)
Пример #2
0
 def start(self):
     if ServerConfig.enable_bonjour:
         application_map = dict((item.split(':')) for item in ServerConfig.application_map)
         for uri, app in application_map.iteritems():
             if app == 'echo':
                 service = BonjourService(service='sipuri', name='Echo Test', uri_user=uri, is_focus=False)
                 service.start()
                 service.presence_state = BonjourPresenceState('available', u'Call me to test your client')
                 self.bonjour_services.add(service)
Пример #3
0
 def start(self):
     self.bonjour_services = []
     if ServerConfig.enable_bonjour:
         application_map = dict((item.split(':')) for item in ServerConfig.application_map)
         for uri, app in application_map.iteritems():
             if app == 'playback':
                 config = get_config('%s' % uri)
                 if config is None:
                     continue
                 if os.path.isfile(config.file) and os.access(config.file, os.R_OK):
                     service = BonjourService(service='sipuri', name='Playback Test', uri_user=uri, is_focus=False)
                     service.start()
                     service.presence_state = BonjourPresenceState('available', u'File: %s' % os.path.basename(config.file))
                     self.bonjour_services.append(service)
Пример #4
0
    def start(self):
        self.web = ConferenceWeb(self)
        web_server.register_resource("conference", self.web.resource())

        # cleanup old files
        for path in (ConferenceConfig.file_transfer_dir, ConferenceConfig.screensharing_images_dir):
            try:
                shutil.rmtree(path)
            except EnvironmentError:
                pass

        if ServerConfig.enable_bonjour and ServerConfig.default_application == "conference":
            self.bonjour_focus_service = BonjourService(service="sipfocus")
            self.bonjour_focus_service.start()
            log.msg("Bonjour publication started for service 'sipfocus'")
            self.bonjour_room_service = BonjourService(service="sipuri", name="Conference Room", uri_user="******")
            self.bonjour_room_service.start()
            self.bonjour_room_service.presence_state = BonjourPresenceState("available", u"No participants")
            log.msg("Bonjour publication started for service 'sipuri'")
Пример #5
0
    def start(self):
        self.web = ConferenceWeb(self)
        web_server.register_resource('conference', self.web.resource())

        # cleanup old files
        for path in (ConferenceConfig.file_transfer_dir, ConferenceConfig.screensharing_images_dir):
            try:
                shutil.rmtree(path)
            except EnvironmentError:
                pass

        if ServerConfig.enable_bonjour and ServerConfig.default_application == 'conference':
            self.bonjour_focus_service = BonjourService(service='sipfocus')
            self.bonjour_focus_service.start()
            log.msg("Bonjour publication started for service 'sipfocus'")
            self.bonjour_room_service = BonjourService(service='sipuri', name='Conference Room', uri_user='******')
            self.bonjour_room_service.start()
            self.bonjour_room_service.presence_state = BonjourPresenceState('available', u'No participants')
            log.msg("Bonjour publication started for service 'sipuri'")
Пример #6
0
 def start(self):
     self.bonjour_services = []
     if ServerConfig.enable_bonjour:
         application_map = dict(
             (item.split(':')) for item in ServerConfig.application_map)
         for uri, app in application_map.iteritems():
             if app == 'playback':
                 config = get_config('%s' % uri)
                 if config is None:
                     continue
                 if os.path.isfile(config.file) and os.access(
                         config.file, os.R_OK):
                     service = BonjourService(service='sipuri',
                                              name='Playback Test',
                                              uri_user=uri,
                                              is_focus=False)
                     service.start()
                     service.presence_state = BonjourPresenceState(
                         'available',
                         u'File: %s' % os.path.basename(config.file))
                     self.bonjour_services.append(service)
Пример #7
0
class ConferenceApplication(SylkApplication):
    implements(IObserver)

    def __init__(self):
        self._rooms = {}
        self.invited_participants_map = {}
        self.bonjour_focus_service = Null
        self.bonjour_room_service = Null
        self.web = Null

    def start(self):
        self.web = ConferenceWeb(self)
        web_server.register_resource("conference", self.web.resource())

        # cleanup old files
        for path in (ConferenceConfig.file_transfer_dir, ConferenceConfig.screensharing_images_dir):
            try:
                shutil.rmtree(path)
            except EnvironmentError:
                pass

        if ServerConfig.enable_bonjour and ServerConfig.default_application == "conference":
            self.bonjour_focus_service = BonjourService(service="sipfocus")
            self.bonjour_focus_service.start()
            log.msg("Bonjour publication started for service 'sipfocus'")
            self.bonjour_room_service = BonjourService(service="sipuri", name="Conference Room", uri_user="******")
            self.bonjour_room_service.start()
            self.bonjour_room_service.presence_state = BonjourPresenceState("available", u"No participants")
            log.msg("Bonjour publication started for service 'sipuri'")

    def stop(self):
        self.bonjour_focus_service.stop()
        self.bonjour_room_service.stop()

    def get_room(self, uri, create=False):
        room_uri = "%s@%s" % (uri.user, uri.host)
        try:
            room = self._rooms[room_uri]
        except KeyError:
            if create:
                room = Room(room_uri)
                self._rooms[room_uri] = room
                return room
            else:
                raise RoomNotFoundError
        else:
            return room

    def remove_room(self, uri):
        room_uri = "%s@%s" % (uri.user, uri.host)
        self._rooms.pop(room_uri, None)

    def validate_acl(self, room_uri, from_uri):
        room_uri = "%s@%s" % (room_uri.user, room_uri.host)
        cfg = get_room_config(room_uri)
        if cfg.access_policy == "allow,deny":
            if cfg.allow.match(from_uri) and not cfg.deny.match(from_uri):
                return
            raise ACLValidationError
        else:
            if cfg.deny.match(from_uri) and not cfg.allow.match(from_uri):
                raise ACLValidationError

    def incoming_session(self, session):
        log.msg("New session from %s to %s" % (session.remote_identity.uri, session.local_identity.uri))
        audio_streams = [stream for stream in session.proposed_streams if stream.type == "audio"]
        chat_streams = [stream for stream in session.proposed_streams if stream.type == "chat"]
        transfer_streams = [stream for stream in session.proposed_streams if stream.type == "file-transfer"]
        if not audio_streams and not chat_streams and not transfer_streams:
            log.msg(u"Session rejected: invalid media, only RTP audio and MSRP chat are supported")
            session.reject(488)
            return
        audio_stream = audio_streams[0] if audio_streams else None
        chat_stream = chat_streams[0] if chat_streams else None
        transfer_stream = transfer_streams[0] if transfer_streams else None

        try:
            self.validate_acl(session.request_uri, session.remote_identity.uri)
        except ACLValidationError:
            log.msg(u"Session rejected: unauthorized by access list")
            session.reject(403)
            return

        if transfer_stream is not None:
            try:
                room = self.get_room(session.request_uri)
            except RoomNotFoundError:
                log.msg(u"Session rejected: room not found")
                session.reject(404)
                return
            if transfer_stream.direction == "sendonly":
                # file transfer 'pull'
                try:
                    file = next(file for file in room.files if file.hash == transfer_stream.file_selector.hash)
                except StopIteration:
                    log.msg(u"Session rejected: requested file not found")
                    session.reject(404)
                    return
                try:
                    transfer_stream.file_selector = file.file_selector
                except EnvironmentError, e:
                    log.msg(u"Session rejected: error opening requested file: %s" % e)
                    session.reject(404)
                    return
            else:
                transfer_stream.handler.save_directory = os.path.join(
                    ConferenceConfig.file_transfer_dir.normalized, room.uri
                )

        NotificationCenter().add_observer(self, sender=session)
        if audio_stream:
            session.send_ring_indication()
        streams = [stream for stream in (audio_stream, chat_stream, transfer_stream) if stream]
        reactor.callLater(4 if audio_stream is not None else 0, self.accept_session, session, streams)
Пример #8
0
class ConferenceApplication(SylkApplication):
    implements(IObserver)

    def __init__(self):
        self._rooms = {}
        self.invited_participants_map = {}
        self.bonjour_focus_service = Null
        self.bonjour_room_service = Null
        self.web = Null

    def start(self):
        self.web = ConferenceWeb(self)
        web_server.register_resource('conference', self.web.resource)

        # cleanup old files
        for path in (ConferenceConfig.file_transfer_dir,
                     ConferenceConfig.screensharing_images_dir):
            try:
                shutil.rmtree(path)
            except EnvironmentError:
                pass

        if ServerConfig.enable_bonjour and ServerConfig.default_application == 'conference':
            self.bonjour_focus_service = BonjourService(service='sipfocus')
            self.bonjour_focus_service.start()
            log.info("Bonjour publication started for service 'sipfocus'")
            self.bonjour_room_service = BonjourService(service='sipuri',
                                                       name='Conference Room',
                                                       uri_user='******')
            self.bonjour_room_service.start()
            self.bonjour_room_service.presence_state = BonjourPresenceState(
                'available', u'No participants')
            log.info("Bonjour publication started for service 'sipuri'")

    def stop(self):
        self.bonjour_focus_service.stop()
        self.bonjour_room_service.stop()

    def get_room(self, uri, create=False):
        room_uri = '%s@%s' % (uri.user, uri.host)
        try:
            room = self._rooms[room_uri]
        except KeyError:
            if create:
                room = Room(room_uri)
                self._rooms[room_uri] = room
                return room
            else:
                raise RoomNotFoundError
        else:
            return room

    def remove_room(self, uri):
        room_uri = '%s@%s' % (uri.user, uri.host)
        self._rooms.pop(room_uri, None)

    def validate_acl(self, room_uri, from_uri):
        room_uri = '%s@%s' % (room_uri.user, room_uri.host)
        cfg = get_room_config(room_uri)
        if cfg.access_policy == 'allow,deny':
            if cfg.allow.match(from_uri) and not cfg.deny.match(from_uri):
                return
            raise ACLValidationError
        else:
            if cfg.deny.match(from_uri) and not cfg.allow.match(from_uri):
                raise ACLValidationError

    def incoming_session(self, session):
        log.info('New session from %s to %s' %
                 (session.remote_identity.uri, session.local_identity.uri))
        audio_streams = [
            stream for stream in session.proposed_streams
            if stream.type == 'audio'
        ]
        chat_streams = [
            stream for stream in session.proposed_streams
            if stream.type == 'chat'
        ]
        transfer_streams = [
            stream for stream in session.proposed_streams
            if stream.type == 'file-transfer'
        ]
        if not audio_streams and not chat_streams and not transfer_streams:
            log.info(u'Session rejected: invalid media')
            session.reject(488)
            return
        audio_stream = audio_streams[0] if audio_streams else None
        chat_stream = chat_streams[0] if chat_streams else None
        transfer_stream = transfer_streams[0] if transfer_streams else None

        try:
            self.validate_acl(session.request_uri, session.remote_identity.uri)
        except ACLValidationError:
            log.info(u'Session rejected: unauthorized by access list')
            session.reject(403)
            return

        if transfer_stream is not None:
            try:
                room = self.get_room(session.request_uri)
            except RoomNotFoundError:
                log.info(u'Session rejected: room not found')
                session.reject(404)
                return
            if transfer_stream.direction == 'sendonly':
                # file transfer 'pull'
                try:
                    file = next(
                        file for file in room.files
                        if file.hash == transfer_stream.file_selector.hash)
                except StopIteration:
                    log.info(u'Session rejected: requested file not found')
                    session.reject(404)
                    return
                try:
                    transfer_stream.file_selector = file.file_selector
                except EnvironmentError as e:
                    log.info(
                        u'Session rejected: error opening requested file: %s' %
                        e)
                    session.reject(404)
                    return
            else:
                transfer_stream.handler.save_directory = os.path.join(
                    ConferenceConfig.file_transfer_dir.normalized, room.uri)

        NotificationCenter().add_observer(self, sender=session)
        if audio_stream:
            session.send_ring_indication()
        streams = [
            stream for stream in (audio_stream, chat_stream, transfer_stream)
            if stream
        ]
        reactor.callLater(4 if audio_stream is not None else 0,
                          self.accept_session, session, streams)

    def incoming_subscription(self, subscribe_request, data):
        from_header = data.headers.get('From', Null)
        to_header = data.headers.get('To', Null)
        if Null in (from_header, to_header):
            subscribe_request.reject(400)
            return

        if subscribe_request.event != 'conference':
            log.info(
                u'Subscription for event %s rejected: only conference event is supported'
                % subscribe_request.event)
            subscribe_request.reject(489)
            return

        try:
            self.validate_acl(data.request_uri, from_header.uri)
        except ACLValidationError:
            try:
                self.validate_acl(to_header.uri, from_header.uri)
            except ACLValidationError:
                # Check if we need to skip the ACL because this was an invited participant
                if not (str(
                        from_header.uri) in self.invited_participants_map.get(
                            '%s@%s' %
                            (data.request_uri.user, data.request_uri.host), {})
                        or str(from_header.uri)
                        in self.invited_participants_map.get(
                            '%s@%s' %
                            (to_header.uri.user, to_header.uri.host), {})):
                    log.info(
                        u'Subscription rejected: unauthorized by access list')
                    subscribe_request.reject(403)
                    return
        try:
            room = self.get_room(data.request_uri)
        except RoomNotFoundError:
            try:
                room = self.get_room(to_header.uri)
            except RoomNotFoundError:
                log.info(u'Subscription rejected: room not yet created')
                subscribe_request.reject(480)
                return
        if not room.started:
            log.info(u'Subscription rejected: room not started yet')
            subscribe_request.reject(480)
        else:
            room.handle_incoming_subscription(subscribe_request, data)

    def incoming_referral(self, refer_request, data):
        from_header = data.headers.get('From', Null)
        to_header = data.headers.get('To', Null)
        refer_to_header = data.headers.get('Refer-To', Null)
        if Null in (from_header, to_header, refer_to_header):
            refer_request.reject(400)
            return

        log.info(u'Room %s - join request from %s to %s' %
                 ('%s@%s' % (to_header.uri.user, to_header.uri.host),
                  from_header.uri, refer_to_header.uri))

        try:
            self.validate_acl(data.request_uri, from_header.uri)
        except ACLValidationError:
            log.info(
                u'Room %s - invite participant request rejected: unauthorized by access list'
                % data.request_uri)
            refer_request.reject(403)
            return
        referral_handler = IncomingReferralHandler(refer_request, data)
        referral_handler.start()

    def incoming_message(self, message_request, data):
        log.info(u'SIP MESSAGE is not supported, use MSRP media instead')
        message_request.answer(405)

    def accept_session(self, session, streams):
        if session.state == 'incoming':
            try:
                session.accept(streams, is_focus=True)
            except IllegalStateError:
                pass

    def add_participant(self, session, room_uri):
        # Keep track of the invited participants, we must skip ACL policy
        # for SUBSCRIBE requests
        room_uri_str = '%s@%s' % (room_uri.user, room_uri.host)
        log.info(u'Room %s - outgoing session to %s started' %
                 (room_uri_str, session.remote_identity.uri))
        d = self.invited_participants_map.setdefault(room_uri_str, {})
        d.setdefault(str(session.remote_identity.uri), 0)
        d[str(session.remote_identity.uri)] += 1
        NotificationCenter().add_observer(self, sender=session)
        room = self.get_room(room_uri, True)
        room.start()
        room.add_session(session)

    def remove_participant(self, participant_uri, room_uri):
        try:
            room = self.get_room(room_uri)
        except RoomNotFoundError:
            pass
        else:
            log.info('Room %s - %s removed from conference' %
                     (room_uri, participant_uri))
            room.terminate_sessions(participant_uri)

    def handle_notification(self, notification):
        handler = getattr(self, '_NH_%s' % notification.name, Null)
        handler(notification)

    def _NH_SIPSessionDidStart(self, notification):
        session = notification.sender
        room = self.get_room(session.request_uri, True)
        room.start()
        room.add_session(session)

    @run_in_green_thread
    def _NH_SIPSessionDidEnd(self, notification):
        session = notification.sender
        notification.center.remove_observer(self, sender=session)
        if session.direction == 'incoming':
            room_uri = session.request_uri
        else:
            # Clear invited participants mapping
            room_uri_str = '%s@%s' % (session.local_identity.uri.user,
                                      session.local_identity.uri.host)
            d = self.invited_participants_map[room_uri_str]
            d[str(session.remote_identity.uri)] -= 1
            if d[str(session.remote_identity.uri)] == 0:
                del d[str(session.remote_identity.uri)]
            room_uri = session.local_identity.uri
        # We could get this notifiction even if we didn't get SIPSessionDidStart
        try:
            room = self.get_room(room_uri)
        except RoomNotFoundError:
            return
        if session in room.sessions:
            room.remove_session(session)
        if not room.stopping and room.empty:
            self.remove_room(room_uri)
            room.stop()

    def _NH_SIPSessionDidFail(self, notification):
        session = notification.sender
        notification.center.remove_observer(self, sender=session)
        log.info(u'Session from %s failed: %s' %
                 (session.remote_identity.uri, notification.data.reason))
Пример #9
0
class ConferenceApplication(SylkApplication):
    implements(IObserver)

    def __init__(self):
        self._rooms = {}
        self.invited_participants_map = {}
        self.bonjour_focus_service = Null
        self.bonjour_room_service = Null
        self.web = Null

    def start(self):
        self.web = ConferenceWeb(self)
        web_server.register_resource('conference', self.web.resource())

        # cleanup old files
        for path in (ConferenceConfig.file_transfer_dir, ConferenceConfig.screensharing_images_dir):
            try:
                shutil.rmtree(path)
            except EnvironmentError:
                pass

        if ServerConfig.enable_bonjour and ServerConfig.default_application == 'conference':
            self.bonjour_focus_service = BonjourService(service='sipfocus')
            self.bonjour_focus_service.start()
            log.msg("Bonjour publication started for service 'sipfocus'")
            self.bonjour_room_service = BonjourService(service='sipuri', name='Conference Room', uri_user='******')
            self.bonjour_room_service.start()
            self.bonjour_room_service.presence_state = BonjourPresenceState('available', u'No participants')
            log.msg("Bonjour publication started for service 'sipuri'")

    def stop(self):
        self.bonjour_focus_service.stop()
        self.bonjour_room_service.stop()

    def get_room(self, uri, create=False):
        room_uri = '%s@%s' % (uri.user, uri.host)
        try:
            room = self._rooms[room_uri]
        except KeyError:
            if create:
                room = Room(room_uri)
                self._rooms[room_uri] = room
                return room
            else:
                raise RoomNotFoundError
        else:
            return room

    def remove_room(self, uri):
        room_uri = '%s@%s' % (uri.user, uri.host)
        self._rooms.pop(room_uri, None)

    def validate_acl(self, room_uri, from_uri):
        room_uri = '%s@%s' % (room_uri.user, room_uri.host)
        cfg = get_room_config(room_uri)
        if cfg.access_policy == 'allow,deny':
            if cfg.allow.match(from_uri) and not cfg.deny.match(from_uri):
                return
            raise ACLValidationError
        else:
            if cfg.deny.match(from_uri) and not cfg.allow.match(from_uri):
                raise ACLValidationError

    def incoming_session(self, session):
        log.msg('New session from %s to %s' % (session.remote_identity.uri, session.local_identity.uri))
        audio_streams = [stream for stream in session.proposed_streams if stream.type=='audio']
        chat_streams = [stream for stream in session.proposed_streams if stream.type=='chat']
        transfer_streams = [stream for stream in session.proposed_streams if stream.type=='file-transfer']
        if not audio_streams and not chat_streams and not transfer_streams:
            log.msg(u'Session rejected: invalid media, only RTP audio and MSRP chat are supported')
            session.reject(488)
            return
        audio_stream = audio_streams[0] if audio_streams else None
        chat_stream = chat_streams[0] if chat_streams else None
        transfer_stream = transfer_streams[0] if transfer_streams else None

        try:
            self.validate_acl(session.request_uri, session.remote_identity.uri)
        except ACLValidationError:
            log.msg(u'Session rejected: unauthorized by access list')
            session.reject(403)
            return

        if transfer_stream is not None:
            try:
                room = self.get_room(session.request_uri)
            except RoomNotFoundError:
                log.msg(u'Session rejected: room not found')
                session.reject(404)
                return
            if transfer_stream.direction == 'sendonly':
                # file transfer 'pull'
                try:
                    file = next(file for file in room.files if file.hash == transfer_stream.file_selector.hash)
                except StopIteration:
                    log.msg(u'Session rejected: requested file not found')
                    session.reject(404)
                    return
                try:
                    transfer_stream.file_selector = file.file_selector
                except EnvironmentError, e:
                    log.msg(u'Session rejected: error opening requested file: %s' % e)
                    session.reject(404)
                    return
            else:
                transfer_stream.handler.save_directory = os.path.join(ConferenceConfig.file_transfer_dir.normalized, room.uri)

        NotificationCenter().add_observer(self, sender=session)
        if audio_stream:
            session.send_ring_indication()
        streams = [stream for stream in (audio_stream, chat_stream, transfer_stream) if stream]
        reactor.callLater(4 if audio_stream is not None else 0, self.accept_session, session, streams)