diff --git a/msrprelay b/msrprelay old mode 100644 new mode 100755 index dbce16d..c24b41d --- a/msrprelay +++ b/msrprelay @@ -1,89 +1,89 @@ -#!/usr/bin/env python +#!/usr/bin/python2 """MSRP Relay""" if __name__ == '__main__': import msrp import sys import signal from application import log from application.process import process, ProcessError from argparse import ArgumentParser name = 'msrprelay' fullname = 'MSRP Relay' description = 'An open source MSRP Relay' process.configuration.user_directory = None process.configuration.subdirectory = name # process.runtime.subdirectory = name parser = ArgumentParser(usage='%(prog)s [options]') parser.add_argument('--version', action='version', version='%(prog)s {}'.format(msrp.__version__)) parser.add_argument('--systemd', action='store_true', help='run as a systemd simple service and log to journal') parser.add_argument('--no-fork', action='store_false', dest='fork', help='run in the foreground and log to the terminal') parser.add_argument('--config-dir', dest='config_directory', default=None, help='the configuration directory ({})'.format(process.configuration.system_directory), metavar='PATH') parser.add_argument('--runtime-dir', dest='runtime_directory', default=None, help='the runtime directory ({})'.format(process.runtime.directory), metavar='PATH') parser.add_argument('--debug', action='store_true', help='enable verbose logging') parser.add_argument('--debug-memory', action='store_true', help='enable memory debugging') options = parser.parse_args() log.Formatter.prefix_format = '{record.levelname:<8s} ' if options.config_directory is not None: process.configuration.local_directory = options.config_directory if options.runtime_directory is not None: process.runtime.directory = options.runtime_directory if options.systemd: from systemd.journal import JournalHandler log.set_handler(JournalHandler(SYSLOG_IDENTIFIER=name)) log.capture_output() elif options.fork: try: process.daemonize(pidfile='{}.pid'.format(name)) except ProcessError, e: log.critical('Cannot start %s: %s' % (fullname, e)) sys.exit(1) log.use_syslog(name) log.info('Starting %s %s' % (fullname, msrp.__version__)) try: process.wait_for_network(wait_time=10, wait_message='Waiting for network to become available...') except KeyboardInterrupt: sys.exit(0) except RuntimeError as e: log.critical('Cannot start %s: %s' % (fullname, e)) sys.exit(1) from msrp.relay import Relay, RelayConfig log.level.current = log.level.DEBUG if options.debug else RelayConfig.log_level if options.debug_memory: from application.debug.memory import memory_dump try: relay = Relay() except Exception, e: log.critical('Failed to create %s: %s' % (fullname, e)) if e.__class__ is not RuntimeError: log.exception() sys.exit(1) process.signals.add_handler(signal.SIGHUP, lambda signum, frame: relay.reload()) try: relay.run() except Exception, e: log.critical('Failed to run %s: %s' % (fullname, e)) if e.__class__ is not RuntimeError: log.exception() sys.exit(1) if options.debug_memory: memory_dump() diff --git a/setup.py b/setup.py old mode 100644 new mode 100755 index 8be15e8..5c415d4 --- a/setup.py +++ b/setup.py @@ -1,36 +1,36 @@ -#!/usr/bin/env python +#!/usr/bin/python2 import msrp import os from distutils.core import setup def find_packages(toplevel): return [directory.replace(os.path.sep, '.') for directory, sub_dirs, files in os.walk(toplevel) if '__init__.py' in files] setup( name='msrprelay', version=msrp.__version__, description='A MSRP Relay.', url='http://msrprelay.org/', author='AG Projects', author_email='support@ag-projects.com', license='GPLv2', platforms=['Platform Independent'], classifiers=[ 'Development Status :: 4 - Beta', 'Intended Audience :: Service Providers', 'License :: OSI Approved :: GNU General Public License (GPL)', 'Operating System :: OS Independent', 'Programming Language :: Python', ], data_files=[('/etc/msrprelay', ['config.ini.sample'])], packages=find_packages('msrp'), scripts=['msrprelay'] ) diff --git a/test/msrp_receive_file.py b/test/msrp_receive_file.py old mode 100644 new mode 100755 index a6ac7a8..3dcc2c2 --- a/test/msrp_receive_file.py +++ b/test/msrp_receive_file.py @@ -1,151 +1,151 @@ -#!/usr/bin/env python +#!/usr/bin/python2 import sys sys.path.append(".") sys.path.append("..") import time from base64 import b64encode from getpass import getpass from twisted.names.srvconnect import SRVConnector from twisted.internet.protocol import ClientFactory from twisted.internet import reactor from gnutls.interfaces.twisted import TLSContext, X509Credentials from msrp.protocol import * from msrp.digest import process_www_authenticate from msrp.responses import * rand_source = open("/dev/urandom") def generate_transaction_id(): return b64encode(rand_source.read(12), "+-") class MSRPFileReceiverFactory(ClientFactory): protocol = MSRPProtocol def __init__(self, username, password, relay_uri): self.uri = URI("localhost", use_tls = True, port = 12345, session_id = b64encode(rand_source.read(12))) self.username = username self.password = password self.relay_uri = relay_uri self.byte_count = 0 self.bytes_expected = 0 self.do_on_start = None self.do_on_data = None self.do_on_end = None def get_peer(self, protocol): self.protocol = protocol reactor.callLater(0, self._send_auth1) return self def data_start(self, msrpdata): if self.do_on_start: self.do_on_start(msrpdata) def write_chunk(self, data): self.byte_count += len(data) print "received %d of %d bytes" % (self.byte_count, self.bytes_expected) if self.do_on_data: self.do_on_data(data) def data_end(self, continuation): if self.do_on_end: self.do_on_end(continuation) def connection_lost(self, reason): print "Connection lost!" def _send_auth1(self): print "Sending initial AUTH" msrpdata = MSRPData(generate_transaction_id(), method = "AUTH") msrpdata.add_header(ToPathHeader([self.relay_uri])) msrpdata.add_header(FromPathHeader([self.uri])) self.protocol.transport.write(msrpdata.encode()) self.do_on_start = self._send_auth2 def _send_auth2(self, msrpdata): print "Got challenge, sending response AUTH" auth, rsp_auth = process_www_authenticate(self.username, self.password, "AUTH", str(self.relay_uri), **msrpdata.headers["WWW-Authenticate"].decoded) msrpdata = MSRPData(generate_transaction_id(), method = "AUTH") msrpdata.add_header(ToPathHeader([self.relay_uri])) msrpdata.add_header(FromPathHeader([self.uri])) msrpdata.add_header(AuthorizationHeader(auth)) self.protocol.transport.write(msrpdata.encode()) self.do_on_start = self._get_path def _get_path(self, msrpdata): if msrpdata.code != 200: print "Failed to authenticate!" if msrpdata.comment: print msrpdata.comment self.protocol.transport.loseConnection() return sdp_path = list(reversed(msrpdata.headers["Use-Path"].decoded)) + [self.uri] print "Path to send in SDP:\n%s" % " ".join(str(uri) for uri in sdp_path) self.full_to_path = " ".join(str(uri) for uri in msrpdata.headers["Use-Path"].decoded) + " " + raw_input("Destination path: ") self.do_on_start = self._start_time def _start_time(self, msrpdata): filename = msrpdata.headers["Content-Disposition"].decoded[1]["filename"] print 'Receiving file "%s"' % filename self.outfile= open(msrpdata.headers["Content-Disposition"].decoded[1]["filename"], "wb") self.start_time = time.time() total = msrpdata.headers["Byte-Range"].decoded[2] if total: self.bytes_expected = total self.do_on_start = None self.do_on_data = self._receive_data self.do_on_end = self._quit def _receive_data(self, data): self.outfile.write(data) def _quit(self, continuation): if continuation == "$": duration = time.time() - self.start_time speed = self.byte_count / duration / 1024 if self.byte_count == self.bytes_expected: print "File transfer completed successfully." else: print "File transfer aborted prematurely!" print "Received %d bytes in %.0f seconds, (%.2f kb/s)" % (self.byte_count, duration, speed) self.protocol.transport.loseConnection() def clientConnectionFailed(self, connector, err): print "Connection failed" print err.value reactor.callLater(0, reactor.stop) def clientConnectionLost(self, connector, err): print "Connection lost" print err.value reactor.callLater(0, reactor.stop) if __name__ == "__main__": if len(sys.argv) < 2 or len(sys.argv) > 4: print "Usage: %s user@domain [relay-hostname [relay-port]]" % sys.argv[0] print "If the hostname and port are not specified, the MSRP relay will be discovered" print "through the the _msrps._tcp.domain SRV record. If a hostname is specified but" print "no port, the default port of 2855 will be used." else: username, domain = sys.argv[1].split("@", 1) cred = X509Credentials(None, None) cred.verify_peer = False ctx = TLSContext(cred) password = getpass() if len(sys.argv) == 2: factory = MSRPFileReceiverFactory(username, password, URI(domain, use_tls=True)) connector = SRVConnector(reactor, "msrps", domain, factory, connectFuncName="connectTLS", connectFuncArgs=[ctx]) connector.connect() else: relay_host = sys.argv[2] if len(sys.argv) == 4: relay_port = int(sys.argv[3]) else: relay_port = 2855 factory = MSRPFileReceiverFactory(username, password, URI(relay_host, port=relay_port, use_tls=True)) reactor.connectTLS(relay_host, relay_port, factory, ctx) reactor.run() diff --git a/test/msrp_send_file.py b/test/msrp_send_file.py old mode 100644 new mode 100755 index 8074c5f..f76151c --- a/test/msrp_send_file.py +++ b/test/msrp_send_file.py @@ -1,161 +1,161 @@ -#!/usr/bin/env python +#!/usr/bin/python2 import sys sys.path.append(".") sys.path.append("..") import time import os from base64 import b64encode from getpass import getpass from twisted.names.srvconnect import SRVConnector from twisted.internet.protocol import ClientFactory from twisted.internet import reactor from gnutls.interfaces.twisted import TLSContext, X509Credentials from msrp.protocol import * from msrp.digest import process_www_authenticate from msrp.responses import * rand_source = open("/dev/urandom") BLOCK_SIZE = 64 * 1024 def generate_transaction_id(): return b64encode(rand_source.read(12), "+-") class MSRPFileSenderFactory(ClientFactory): protocol = MSRPProtocol def __init__(self, username, password, relay_uri, infile, filename): self.uri = URI("localhost", use_tls = True, port = 12345, session_id = b64encode(rand_source.read(12))) self.username = username self.password = password self.relay_uri = relay_uri self.infile = infile self.filename = filename self.byte_count = 0 self.do_on_start = None self.do_on_data = None self.do_on_end = None self.start_time = None self.complete = False def get_peer(self, protocol): self.protocol = protocol reactor.callLater(0, self._send_auth1) return self def data_start(self, msrpdata): if self.do_on_start: self.do_on_start(msrpdata) def write_chunk(self, data): self.byte_count += len(data) print "received %d bytes, total %d" % (len(data), self.byte_count) if self.do_on_data: self.do_on_data(data) def data_end(self, continuation): if self.do_on_end: self.do_on_end(continuation) def connection_lost(self, reason): print "Connection lost!" if self.complete: duration = time.time() - self.start_time speed = self.file_size / duration / 1024 print "Sent %d bytes in %.0f seconds, (%.2f kb/s)" % (self.file_size, duration, speed) else: print "File transfer was aborted prematurely." def _send_auth1(self): print "Sending initial AUTH" msrpdata = MSRPData(generate_transaction_id(), method = "AUTH") msrpdata.add_header(ToPathHeader([self.relay_uri])) msrpdata.add_header(FromPathHeader([self.uri])) self.protocol.transport.write(msrpdata.encode()) self.do_on_start = self._send_auth2 def _send_auth2(self, msrpdata): print "Got challenge, sending response AUTH" auth, rsp_auth = process_www_authenticate(self.username, self.password, "AUTH", str(self.relay_uri), **msrpdata.headers["WWW-Authenticate"].decoded) msrpdata = MSRPData(generate_transaction_id(), method = "AUTH") msrpdata.add_header(ToPathHeader([self.relay_uri])) msrpdata.add_header(FromPathHeader([self.uri])) msrpdata.add_header(AuthorizationHeader(auth)) self.protocol.transport.write(msrpdata.encode()) self.do_on_start = self._get_path def _get_path(self, msrpdata): if msrpdata.code != 200: print "Failed to authenticate!" if msrpdata.comment: print msrpdata.comment self.protocol.transport.loseConnection() return sdp_path = list(reversed(msrpdata.headers["Use-Path"].decoded)) + [self.uri] print "Path to send in SDP:\n%s" % " ".join(str(uri) for uri in sdp_path) self.full_to_path = " ".join(str(uri) for uri in msrpdata.headers["Use-Path"].decoded) + " " + raw_input("Destination path: ") print 'Starting transmission of "%s"' % self.filename self.do_on_start = None self.infile.seek(0, 2) self.file_size = self.infile.tell() self.infile.seek(0, 0) msrpdata = MSRPData(generate_transaction_id(), method = "SEND") msrpdata.add_header(FromPathHeader([self.uri])) msrpdata.add_header(MSRPHeader("To-Path", self.full_to_path)) msrpdata.add_header(MessageIDHeader("1")) msrpdata.add_header(ByteRangeHeader([1, self.file_size, self.file_size])) msrpdata.add_header(ContentTypeHeader("binary/octet-stream")) msrpdata.add_header(FailureReportHeader("no")) msrpdata.add_header(ContentDispositionHeader(["attachment", {"filename": self.filename}])) self.start_time = time.time() self.protocol.transport.write(msrpdata.encode_start()) sent = 0 for i in range(0, self.file_size, BLOCK_SIZE): print "sent %d of %d bytes" % (sent, self.file_size) sent += i data = self.infile.read(BLOCK_SIZE) self.protocol.transport.write(data) print "File transfer completed." self.complete = True self.protocol.transport.write(msrpdata.encode_end("$")) def clientConnectionFailed(self, connector, err): print "Connection failed" print err.value reactor.callLater(0, reactor.stop) def clientConnectionLost(self, connector, err): print "Connection lost" print err.value reactor.callLater(0, reactor.stop) if __name__ == "__main__": if len(sys.argv) < 3 or len(sys.argv) > 5: print "Usage: %s infile user@domain [relay-hostname [relay-port]]" % sys.argv[0] print "If the hostname and port are not specified, the MSRP relay will be discovered" print "through the the _msrps._tcp.domain SRV record. If a hostname is specified but" print "no port, the default port of 2855 will be used." else: filename = sys.argv[1] infile = open(filename, "rb") username, domain = sys.argv[2].split("@", 1) cred = X509Credentials(None, None) cred.verify_peer = False ctx = TLSContext(cred) password = getpass() if len(sys.argv) == 3: factory = MSRPFileSenderFactory(username, password, URI(domain, use_tls = True), infile, filename.split(os.path.sep)[-1]) connector = SRVConnector(reactor, "msrps", domain, factory, connectFuncName="connectTLS", connectFuncArgs=[ctx]) connector.connect() else: relay_host = sys.argv[3] if len(sys.argv) == 5: relay_port = int(sys.argv[4]) else: relay_port = 2855 factory = MSRPFileSenderFactory(username, password, URI(relay_host, port = relay_port, use_tls = True), infile, filename.split(os.path.sep)[-1]) reactor.connectTLS(relay_host, relay_port, factory, ctx) reactor.run()