예제 #1
0
 def _msrp_reader(self):
     while True:
         try:
             chunk = self.msrp.read_chunk()
             if chunk.method in (None, 'REPORT'):
                 continue
             elif chunk.method == 'SEND':
                 if chunk.content_type in self.accept_types:
                     self.incoming_queue.send(chunk.data)
                     response = make_response(chunk, 200, 'OK')
                     report = make_report(chunk, 200, 'OK')
                 else:
                     response = make_response(chunk, 415,
                                              'Invalid Content-Type')
                     report = None
             else:
                 response = make_response(chunk, 501, 'Unknown method')
                 report = None
             if response is not None:
                 self.msrp.write_chunk(response)
             if report is not None:
                 self.msrp.write_chunk(report)
         except Exception as e:
             self.msrp_reader_thread = None  # avoid issues caused by the notification handler killing this greenlet during post_notification
             if self.shutting_down and isinstance(e, ConnectionDone):
                 break
             self._failure_reason = str(e)
             NotificationCenter().post_notification(
                 'MediaStreamDidFail',
                 sender=self,
                 data=NotificationData(context='reading',
                                       reason=self._failure_reason))
             break
예제 #2
0
    def _reader(self):
        """Wait forever for new chunks. Notify the user about the good ones through self._on_incoming_cb.

        If a response to a previously sent chunk is received, pop the corresponding
        response_cb from self.expected_responses and send the response there.
        """
        error = Failure(ConnectionDone())
        try:
            self.writer_job.link(self.reader_job)
            try:
                while self.state in ['CONNECTED', 'FLUSHING']:
                    chunk = self.msrp.read_chunk()
                    if chunk.method is None:  # response
                        self._handle_incoming_response(chunk)
                    else:
                        method = getattr(self,
                                         '_handle_incoming_%s' % chunk.method,
                                         None)
                        if method is not None:
                            method(chunk)
                        else:
                            response = make_response(chunk, 501,
                                                     'Method unknown')
                            self.outgoing.send(OutgoingChunk(response))
            except proc.LinkedExited:  # writer has exited
                pass
            finally:
                self.writer_job.unlink(self.reader_job)
                self.writer_job.kill()
            self.logger.debug('reader: expecting responses only')
            delay = time() - self.last_expected_response
            if delay >= 0 and self.expected_responses:
                # continue read the responses until the last timeout expires
                with api.timeout(delay, None):
                    while self.expected_responses:
                        chunk = self.msrp.read_chunk()
                        if chunk.method is None:
                            self._handle_incoming_response(chunk)
                        else:
                            self.logger.debug('dropping incoming %r', chunk)
                # read whatever left in the queue
                with api.timeout(0, None):
                    while self.msrp._queue:
                        chunk = self.msrp.read_chunk()
                        if chunk.method is None:
                            self._handle_incoming_response(chunk)
                        else:
                            self.logger.debug('dropping incoming %r', chunk)
            self.logger.debug('reader: done')
        except ConnectionClosedErrors as e:
            self.logger.debug('reader: exiting because of %r', e)
            error = Failure(e)
        except Exception:
            self.logger.exception('reader: captured unhandled exception:')
            error = Failure()
            raise
        finally:
            self._on_incoming_cb(error=error)
            self.msrp.loseConnection(wait=False)
            self.set_state('DONE')
예제 #3
0
 def process_chunk(self, chunk):
     if chunk.method == 'SEND':
         if not self.received_chunks and chunk.byte_range.start == 1:
             self.stream.file_selector.fd.truncate(0)
             self.stream.file_selector.fd.seek(0)
             self.hash = sha1()
             self.offset = 0
         self.received_chunks += 1
         self.queue.put(chunk)
     elif chunk.method == 'FILE_OFFSET':
         if self.received_chunks > 0:
             response = make_response(chunk, 413, 'Unwanted message')
         else:
             offset = self.stream.file_selector.fd.tell()
             response = make_response(chunk, 200, 'OK')
             response.add_header(OffsetHeader(offset))
         self.stream.msrp_session.send_chunk(response)
예제 #4
0
 def process_chunk(self, chunk):
     if chunk.method == 'SEND':
         if not self.received_chunks and chunk.byte_range[0] == 1:
             self.stream.file_selector.fd.truncate(0)
             self.stream.file_selector.fd.seek(0)
             self.hash = sha1()
             self.offset = 0
         self.received_chunks += 1
         self.queue.put(chunk)
     elif chunk.method == 'FILE_OFFSET':
         if self.received_chunks > 0:
             response = make_response(chunk, 413, 'Unwanted message')
         else:
             offset = self.stream.file_selector.fd.tell()
             response = make_response(chunk, 200, 'OK')
             response.headers['Offset'] = MSRPHeader('Offset', offset)
         self.stream.msrp_session.send_chunk(response)
예제 #5
0
    def _reader(self):
        """Wait forever for new chunks. Notify the user about the good ones through self._on_incoming_cb.

        If a response to a previously sent chunk is received, pop the corresponding
        response_cb from self.expected_responses and send the response there.
        """
        error = Failure(ConnectionDone())
        try:
            self.writer_job.link(self.reader_job)
            try:
                while self.state in ['CONNECTED', 'FLUSHING']:
                    chunk = self.msrp.read_chunk()
                    if chunk.method is None: # response
                        self._handle_incoming_response(chunk)
                    else:
                        method = getattr(self, '_handle_incoming_%s' % chunk.method, None)
                        if method is not None:
                            method(chunk)
                        else:
                            response = make_response(chunk, 501, 'Method unknown')
                            self.outgoing.send(OutgoingChunk(response))
            except proc.LinkedExited: # writer has exited
                pass
            finally:
                self.writer_job.unlink(self.reader_job)
                self.writer_job.kill()
            self.logger.debug('reader: expecting responses only')
            delay = time() - self.last_expected_response
            if delay>=0 and self.expected_responses:
                # continue read the responses until the last timeout expires
                with api.timeout(delay, None):
                    while self.expected_responses:
                        chunk = self.msrp.read_chunk()
                        if chunk.method is None:
                            self._handle_incoming_response(chunk)
                        else:
                            self.logger.debug('dropping incoming %r' % chunk)
                # read whatever left in the queue
                with api.timeout(0, None):
                    while self.msrp._queue:
                        chunk = self.msrp.read_chunk()
                        if chunk.method is None:
                            self._handle_incoming_response(chunk)
                        else:
                            self.logger.debug('dropping incoming %r' % chunk)
            self.logger.debug('reader: done')
        except ConnectionClosedErrors, ex:
            self.logger.debug('reader: exiting because of %r' % ex)
            error=Failure(ex)
예제 #6
0
 def _handle_incoming_SEND(self, chunk):
     error = self._check_incoming_SEND(chunk)
     if error is None:
         code, comment = 200, 'OK'
     else:
         code, comment = error.code, error.comment
     response = make_response(chunk, code, comment)
     if response is not None:
         self.outgoing.send(OutgoingChunk(response))
     if code == 200:
         self._on_incoming_cb(chunk)
         if self.automatic_reports:
             report = make_report(chunk, 200, 'OK')
             if report is not None:
                 self.outgoing.send(OutgoingChunk(report))
예제 #7
0
 def _handle_incoming_SEND(self, chunk):
     error = self._check_incoming_SEND(chunk)
     if error is None:
         code, comment = 200, 'OK'
     else:
         code, comment = error.code, error.comment
     response = make_response(chunk, code, comment)
     if response is not None:
         self.outgoing.send(OutgoingChunk(response))
     if code == 200:
         self._on_incoming_cb(chunk)
         if self.automatic_reports:
             report = make_report(chunk, 200, 'OK')
             if report is not None:
                 self.outgoing.send(OutgoingChunk(report))
예제 #8
0
 def _handle_incoming_SEND(self, chunk):
     error = self._check_incoming_SEND(chunk)
     if error is None:
         code, comment = 200, 'OK'
     else:
         code, comment = error.code, error.comment
     if chunk.final:
         response = make_response(chunk, code, comment)
         if response is not None:
             self.outgoing.send((response, None))
     if code == 200:
         self._on_incoming_cb(chunk)
         report = make_report(chunk, 200, 'OK')
         if report is not None:
             self.outgoing.send((report, None))
예제 #9
0
 def _handle_FILE_OFFSET(self, chunk):
     if self.direction != 'recvonly':
         response = make_response(chunk, 413, 'Unwanted message')
         self.msrp_session.send_chunk(response)
         return
     self.handler.process_chunk(chunk)
예제 #10
0
 def _handle_FILE_OFFSET(self, chunk):
     if self.direction != 'recvonly':
         response = make_response(chunk, 413, 'Unwanted message')
         self.msrp_session.send_chunk(response)
         return
     self.handler.process_chunk(chunk)
예제 #11
0
 def _handle_incoming_NICKNAME(self, chunk):
     if 'Use-Nickname' not in chunk.headers or 'Success-Report' in chunk.headers or 'Failure-Report' in chunk.headers:
         response = make_response(chunk, 400, 'Bad request')
         self.outgoing.send(OutgoingChunk(response))
         return
     self._on_incoming_cb(chunk)
예제 #12
0
 def _handle_incoming_NICKNAME(self, chunk):
     if 'Use-Nickname' not in chunk.headers or 'Success-Report' in chunk.headers or 'Failure-Report' in chunk.headers:
         response = make_response(chunk, 400, 'Bad request')
         self.outgoing.send(OutgoingChunk(response))
         return
     self._on_incoming_cb(chunk)