Commit ad9370af authored by Emmanuel Gil Peyrot's avatar Emmanuel Gil Peyrot

Fix a bunch of issues in common.jingle*.

parent 57fb80f1
......@@ -142,6 +142,10 @@ SHOW_LIST = ['offline', 'connecting', 'online', 'chat', 'away', 'xa', 'dnd',
# zeroconf account name
ZEROCONF_ACC_NAME = 'Local'
# These will be set in gajim.gui_interface.
idlequeue = None
socks5queue = None
HAVE_ZEROCONF = True
try:
__import__('avahi')
......
......@@ -28,19 +28,21 @@ Handles the jingle signalling protocol
# * config:
# - codecs
import logging
import nbxmpp
from common import helpers
from common import gajim
from common.jingle_session import JingleSession, JingleStates
if gajim.HAVE_FARSTREAM:
from common.jingle_rtp import JingleAudio, JingleVideo
from common.jingle_ft import JingleFileTransfer
from common.jingle_transport import JingleTransportSocks5, JingleTransportIBB
if gajim.HAVE_FARSTREAM:
from common.jingle_rtp import JingleAudio, JingleVideo
import logging
logger = logging.getLogger('gajim.c.jingle')
class ConnectionJingle(object):
"""
This object depends on that it is a part of Connection class.
......@@ -80,7 +82,7 @@ class ConnectionJingle(object):
try:
jid = helpers.get_full_jid_from_iq(stanza)
except helpers.InvalidFormat:
logger.warn('Invalid JID: %s, ignoring it' % stanza.getFrom())
logger.warning('Invalid JID: %s, ignoring it', stanza.getFrom())
return
id_ = stanza.getID()
if (jid, id_) in self.__iq_responses.keys():
......@@ -102,14 +104,14 @@ class ConnectionJingle(object):
if sid not in self._sessions:
#TODO: tie-breaking and other things...
newjingle = JingleSession(con=self, weinitiate=False, jid=jid,
iq_id=id_, sid=sid)
iq_id=id_, sid=sid)
self._sessions[sid] = newjingle
# we already have such session in dispatcher...
self._sessions[sid].collect_iq_id(id_)
self._sessions[sid].on_stanza(stanza)
# Delete invalid/unneeded sessions
if sid in self._sessions and \
self._sessions[sid].state == JingleStates.ended:
self._sessions[sid].state == JingleStates.ENDED:
self.delete_jingle_session(sid)
raise nbxmpp.NodeProcessed
......@@ -132,20 +134,20 @@ class ConnectionJingle(object):
jingle = self.get_jingle_session(jid, media='audio')
if jingle:
jingle.add_content('video', JingleVideo(jingle, in_xid=in_xid,
out_xid=out_xid))
out_xid=out_xid))
else:
jingle = JingleSession(self, weinitiate=True, jid=jid)
self._sessions[jingle.sid] = jingle
jingle.add_content('video', JingleVideo(jingle, in_xid=in_xid,
out_xid=out_xid))
out_xid=out_xid))
jingle.start_session()
return jingle.sid
def start_file_transfer(self, jid, file_props, request=False):
logger.info("start file transfer with file: %s" % file_props)
logger.info("start file transfer with file: %s", file_props)
contact = gajim.contacts.get_contact_with_highest_priority(self.name,
gajim.get_jid_without_resource(jid))
if gajim.contacts.is_gc_contact(self.name,jid):
gajim.get_jid_without_resource(jid))
if gajim.contacts.is_gc_contact(self.name, jid):
gcc = jid.split('/')
if len(gcc) == 2:
contact = gajim.contacts.get_gc_contact(self.name, gcc[0], gcc[1])
......@@ -162,7 +164,8 @@ class ConnectionJingle(object):
elif contact.supports(nbxmpp.NS_JINGLE_IBB):
transport = JingleTransportIBB()
c = JingleFileTransfer(jingle, transport=transport,
file_props=file_props, use_security=use_security)
file_props=file_props,
use_security=use_security)
file_props.algo = self.__hash_support(contact)
jingle.add_content('file' + helpers.get_random_string_16(), c)
jingle.start_session()
......
......@@ -37,7 +37,7 @@ class JingleContentSetupException(Exception):
"""
class JingleContent(object):
class JingleContent:
"""
An abstraction of content in Jingle sessions
"""
......@@ -48,8 +48,8 @@ class JingleContent(object):
# will be filled by JingleSession.add_content()
# don't uncomment these lines, we will catch more buggy code then
# (a JingleContent not added to session shouldn't send anything)
#self.creator = None
#self.name = None
self.creator = None
self.name = None
self.accepted = False
self.sent = False
self.negotiated = False
......@@ -59,35 +59,39 @@ class JingleContent(object):
self.senders = 'both' #FIXME
self.allow_sending = True # Used for stream direction, attribute 'senders'
# These were found by the Politie
self.file_props = None
self.use_security = None
self.callbacks = {
# these are called when *we* get stanzas
'content-accept': [self.__on_transport_info,
self.__on_content_accept],
'content-add': [self.__on_transport_info],
'content-modify': [],
'content-reject': [],
'content-remove': [],
'description-info': [],
'security-info': [],
'session-accept': [self.__on_transport_info,
self.__on_content_accept],
'session-info': [],
'session-initiate': [self.__on_transport_info],
'session-terminate': [],
'transport-info': [self.__on_transport_info],
'transport-replace': [self.__on_transport_replace],
'transport-accept': [],
'transport-reject': [],
'iq-result': [],
'iq-error': [],
# these are called when *we* sent these stanzas
'content-accept-sent': [self.__fill_jingle_stanza,
self.__on_content_accept],
'content-add-sent': [self.__fill_jingle_stanza],
'session-initiate-sent': [self.__fill_jingle_stanza],
'session-accept-sent': [self.__fill_jingle_stanza,
self.__on_content_accept],
'session-terminate-sent': [],
# these are called when *we* get stanzas
'content-accept': [self.__on_transport_info,
self.__on_content_accept],
'content-add': [self.__on_transport_info],
'content-modify': [],
'content-reject': [],
'content-remove': [],
'description-info': [],
'security-info': [],
'session-accept': [self.__on_transport_info,
self.__on_content_accept],
'session-info': [],
'session-initiate': [self.__on_transport_info],
'session-terminate': [],
'transport-info': [self.__on_transport_info],
'transport-replace': [self.__on_transport_replace],
'transport-accept': [],
'transport-reject': [],
'iq-result': [],
'iq-error': [],
# these are called when *we* sent these stanzas
'content-accept-sent': [self.__fill_jingle_stanza,
self.__on_content_accept],
'content-add-sent': [self.__fill_jingle_stanza],
'session-initiate-sent': [self.__fill_jingle_stanza],
'session-accept-sent': [self.__fill_jingle_stanza,
self.__on_content_accept],
'session-terminate-sent': [],
}
def is_ready(self):
......@@ -134,8 +138,8 @@ class JingleContent(object):
if payload is None:
payload = []
return nbxmpp.Node('content',
attrs={'name': self.name, 'creator': self.creator},
payload=payload)
attrs={'name': self.name, 'creator': self.creator},
payload=payload)
def send_candidate(self, candidate):
"""
......@@ -191,17 +195,16 @@ class JingleContent(object):
file_tag.addChild(node=node)
if self.file_props.type_ == 'r':
if self.file_props.hash_:
h = file_tag.addChild('hash', attrs={
'algo': self.file_props.algo}, namespace=nbxmpp.NS_HASHES,
payload=self.file_props.hash_)
file_tag.addChild('hash', attrs={'algo': self.file_props.algo},
namespace=nbxmpp.NS_HASHES,
payload=self.file_props.hash_)
else:
# if the file is less than 10 mb, then it is small
# lets calculate it right away
if self.file_props.size < 10000000 and not \
self.file_props.hash_:
h = self._calcHash()
if h:
file_tag.addChild(node=h)
if self.file_props.size < 10000000 and not self.file_props.hash_:
hash_data = content._compute_hash()
if hash_data:
file_tag.addChild(node=hash_data)
pjid = gajim.get_jid_without_resource(self.session.peerjid)
file_info = {'name' : self.file_props.name,
'file-name' : self.file_props.file_name,
......@@ -223,9 +226,9 @@ class JingleContent(object):
cert = load_cert_file(certpath)
if cert:
try:
digest_algo = cert.get_signature_algorithm().decode('utf-8'
).split('With')[0]
except AttributeError as e:
digest_algo = (cert.get_signature_algorithm()
.decode('utf-8').split('With')[0])
except AttributeError:
# Old py-OpenSSL is missing get_signature_algorithm
digest_algo = "sha256"
security.addChild('fingerprint').addData(cert.digest(
......@@ -240,5 +243,3 @@ class JingleContent(object):
def destroy(self):
self.callbacks = None
del self.session.contents[(self.creator, self.name)]
This diff is collapsed.
......@@ -13,11 +13,14 @@
## You should have received a copy of the GNU General Public License
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
from common import gajim
import nbxmpp
from common.jingle_transport import *
from common import gajim
from common.jingle_transport import TransportType
from common.socks5 import Socks5ReceiverClient, Socks5SenderClient
import logging
log = logging.getLogger('gajim.c.jingle_ftstates')
class JingleFileTransferStates:
'''
......@@ -31,7 +34,7 @@ class JingleFileTransferStates:
'''
This method MUST be overriden by a subclass
'''
raise Exception('This is an abstract method!!')
raise NotImplementedError('This is an abstract method!')
class StateInitialized(JingleFileTransferStates):
......@@ -50,8 +53,10 @@ class StateInitialized(JingleFileTransferStates):
fingerprint = 'client'
# Connect to the candidate host, on success call on_connect method
gajim.socks5queue.connect_to_hosts(self.jft.session.connection.name,
self.jft.file_props.sid, self.jft.on_connect,
self.jft._on_connect_error, fingerprint=fingerprint)
self.jft.file_props.sid,
self.jft.on_connect,
self.jft._on_connect_error,
fingerprint=fingerprint)
class StateCandSent(JingleFileTransferStates):
......@@ -59,7 +64,7 @@ class StateCandSent(JingleFileTransferStates):
This state sends our nominated candidate
'''
def _sendCand(self, args):
def _send_candidate(self, args):
if 'candError' in args:
self.jft.nominated_cand['our-cand'] = False
self.jft.send_error_candidate()
......@@ -80,16 +85,16 @@ class StateCandSent(JingleFileTransferStates):
self.jft.session.send_transport_info(content)
def action(self, args=None):
self._sendCand(args)
self._send_candidate(args)
class StateCandReceived(JingleFileTransferStates):
class StateCandReceived(JingleFileTransferStates):
'''
This state happens when we receive a candidate.
It takes the arguments: canError if we receive a candidate-error
'''
def _recvCand(self, args):
def _recv_candidate(self, args):
if 'candError' in args:
return
content = args['content']
......@@ -100,17 +105,17 @@ class StateCandReceived(JingleFileTransferStates):
if cand['candidate_id'] == streamhost_cid:
streamhost_used = cand
break
if streamhost_used == None:
if streamhost_used is None:
log.info("unknow streamhost")
return
# We save the candidate nominated by peer
self.jft.nominated_cand['peer-cand'] = streamhost_used
def action(self, args=None):
self._recvCand(args)
self._recv_candidate(args)
class StateCandSentAndRecv( StateCandSent, StateCandReceived):
class StateCandSentAndRecv(StateCandSent, StateCandReceived):
'''
This state happens when we have received and sent the candidates.
It takes the boolean argument: sendCand in order to decide whether
......@@ -119,9 +124,9 @@ class StateCandSentAndRecv( StateCandSent, StateCandReceived):
def action(self, args=None):
if args['sendCand']:
self._sendCand(args)
self._send_candidate(args)
else:
self._recvCand(args)
self._recv_candidate(args)
class StateTransportReplace(JingleFileTransferStates):
......@@ -139,16 +144,16 @@ class StateTransfering(JingleFileTransferStates):
we have.
'''
def __start_IBB_transfer(self, con):
def _start_ibb_transfer(self, con):
self.jft.file_props.transport_sid = self.jft.transport.sid
fp = open(self.jft.file_props.file_name, 'r')
con.OpenStream( self.jft.file_props.sid, self.jft.session.peerjid, fp,
blocksize=4096)
con.OpenStream(self.jft.file_props.sid, self.jft.session.peerjid, fp,
blocksize=4096)
def __start_SOCK5_transfer(self):
def _start_sock5_transfer(self):
# It tells wether we start the transfer as client or server
mode = None
if self.jft.isOurCandUsed():
if self.jft.is_our_candidate_used():
mode = 'client'
streamhost_used = self.jft.nominated_cand['our-cand']
gajim.socks5queue.remove_server(self.jft.file_props.sid)
......@@ -191,34 +196,34 @@ class StateTransfering(JingleFileTransferStates):
gajim.socks5queue.idx += 1
idx = gajim.socks5queue.idx
sockobj = Socks5SenderClient(gajim.idlequeue, idx,
gajim.socks5queue, _sock=None,
host=str(streamhost_used['host']),
port=int(streamhost_used['port']), fingerprint=None,
connected=False, file_props=self.jft.file_props)
gajim.socks5queue, _sock=None,
host=str(streamhost_used['host']),
port=int(streamhost_used['port']),
fingerprint=None, connected=False,
file_props=self.jft.file_props)
else:
sockobj = Socks5ReceiverClient(gajim.idlequeue, streamhost_used,
sid=self.jft.file_props.sid,
file_props=self.jft.file_props, fingerprint=None)
sid=self.jft.file_props.sid,
file_props=self.jft.file_props,
fingerprint=None)
sockobj.proxy = True
sockobj.streamhost = streamhost_used
gajim.socks5queue.add_sockobj(self.jft.session.connection.name,
sockobj)
sockobj)
streamhost_used['idx'] = sockobj.queue_idx
# If we offered the nominated candidate used, we activate
# the proxy
if not self.jft.isOurCandUsed():
if not self.jft.is_our_candidate_used():
gajim.socks5queue.on_success[self.jft.file_props.sid] = \
self.jft.transport._on_proxy_auth_ok
# TODO: add on failure
else:
jid = gajim.get_jid_without_resource(self.jft.session.ourjid)
gajim.socks5queue.send_file(self.jft.file_props,
self.jft.session.connection.name, mode)
self.jft.session.connection.name, mode)
def action(self, args=None):
if self.jft.transport.type_ == TransportType.IBB:
self.__start_IBB_transfer(self.jft.session.connection)
self._start_ibb_transfer(self.jft.session.connection)
elif self.jft.transport.type_ == TransportType.SOCKS5:
self.__start_SOCK5_transfer()
self._start_sock5_transfer()
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -16,13 +16,15 @@
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
##
import logging
import os
import nbxmpp
import logging
import nbxmpp
from common import gajim
log = logging.getLogger('gajim.c.jingle_xtls')
PYOPENSSL_PRESENT = False
# key-exchange id -> [callback, args], accept that session once key-exchange completes
......@@ -53,7 +55,7 @@ DH_PARAMS = 'dh_params.pem'
DEFAULT_DH_PARAMS = 'dh4096.pem'
def default_callback(connection, certificate, error_num, depth, return_code):
log.info("certificate: %s" % certificate)
log.info("certificate: %s", certificate)
return return_code
def load_cert_file(cert_path, cert_store=None):
......@@ -65,8 +67,8 @@ def load_cert_file(cert_path, cert_store=None):
try:
f = open(cert_path)
except IOError as e:
log.warning('Unable to open certificate file %s: %s' % (cert_path,
str(e)))
log.warning('Unable to open certificate file %s: %s', cert_path,
str(e))
return None
lines = f.readlines()
i = 0
......@@ -84,11 +86,11 @@ def load_cert_file(cert_path, cert_store=None):
f.close()
return x509cert
except OpenSSL.crypto.Error as exception_obj:
log.warning('Unable to load a certificate from file %s: %s' %\
(cert_path, exception_obj.args[0][0][2]))
log.warning('Unable to load a certificate from file %s: %s',
cert_path, exception_obj.args[0][0][2])
except:
log.warning('Unknown error while loading certificate from file '
'%s' % cert_path)
'%s', cert_path)
begin = -1
i += 1
f.close()
......@@ -105,7 +107,7 @@ def get_context(fingerprint, verify_cb=None, remote_jid=None):
if fingerprint == 'server': # for testing purposes only
ctx.set_verify(SSL.VERIFY_NONE|SSL.VERIFY_FAIL_IF_NO_PEER_CERT,
verify_cb or default_callback)
verify_cb or default_callback)
elif fingerprint == 'client':
ctx.set_verify(SSL.VERIFY_PEER, verify_cb or default_callback)
......@@ -121,23 +123,23 @@ def get_context(fingerprint, verify_cb=None, remote_jid=None):
ctx.load_tmp_dh(dh_params_name.encode('utf-8'))
except FileNotFoundError as err:
default_dh_params_name = os.path.join(gajim.DATA_DIR,
'other', DEFAULT_DH_PARAMS)
'other', DEFAULT_DH_PARAMS)
try:
with open(default_dh_params_name, "r") as default_dh_params_file:
ctx.load_tmp_dh(default_dh_params_name.encode('utf-8'))
except FileNotFoundError as err:
log.error('Unable to load default DH parameter file: %s , %s'
% (default_dh_params_name, err))
log.error('Unable to load default DH parameter file: %s, %s',
default_dh_params_name, err)
raise
if remote_jid:
store = ctx.get_cert_store()
path = os.path.join(os.path.expanduser(gajim.MY_PEER_CERTS_PATH),
remote_jid) + '.cert'
remote_jid) + '.cert'
if os.path.exists(path):
load_cert_file(path, cert_store=store)
log.debug('certificate file ' + path + ' loaded fingerprint ' + \
fingerprint)
log.debug('certificate file %s loaded fingerprint %s',
path, fingerprint)
return ctx
def read_cert(certpath):
......@@ -212,16 +214,16 @@ def send_cert_request(con, to_jid):
# the following code is partly due to pyopenssl examples
def createKeyPair(type, bits):
def createKeyPair(type_, bits):
"""
Create a public/private key pair.
Arguments: type - Key type, must be one of TYPE_RSA and TYPE_DSA
Arguments: type_ - Key type, must be one of TYPE_RSA and TYPE_DSA
bits - Number of bits to use in the key
Returns: The public/private key pair in a PKey object
"""
pkey = crypto.PKey()
pkey.generate_key(type, bits)
pkey.generate_key(type_, bits)
return pkey
def createCertRequest(pkey, digest="sha256", **name):
......@@ -244,7 +246,7 @@ def createCertRequest(pkey, digest="sha256", **name):
req = crypto.X509Req()
subj = req.get_subject()
for (key,value) in name.items():
for (key, value) in name.items():
setattr(subj, key, value)
req.set_pubkey(pkey)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment