def tlsn_msg_receiver(my_nick,counterparty_nick,ack_queue,recv_queue,message_headers,pk,seq_init=100000): '''Intended to be run as a thread; puts msgs sent to my_nick from counterparty_nick onto the Queue recv_queue, and sends acknowledgements onto ack_queue, filtering out messages whose headers/topics are not in message_headers, and using sequence numbering starting from seq_init (or 0 if seq_init is undef). Messages are received in chunks and decrypted using private key pk and base64 decoded, then reassembled according to line endings CRLF and EOL, as per tlsnotary's messaging protocol. ''' if not initialized: raise Exception("TLSN Messaging not yet instantiated") if not hasattr(tlsn_msg_receiver, 'last_seq_which_i_acked'): if not seq_init: seq_init=0 tlsn_msg_receiver.last_seq_which_i_acked = seq_init #static variable. Initialized only on first function's run chunks = [] while True: eemsg = mi.msg_receiver(my_nick,counterparty_nick) if not eemsg: continue #note that the timeout is in the implementation layer #acknowledgements are not our business here; put them on the queue if eemsg[0].startswith('ack'): #acks are not encrypted ack_queue.put(eemsg[0][len('ack:'):]) continue if len(eemsg) !=3: continue if not eemsg[0].startswith('seq'): continue #wrong format; old server hellos will do this msg_decrypted = dd(eemsg[1],pk) #print ("decrypted message is: ",msg_decrypted) if len(chunks) == 0: msg = [msg_decrypted.split(':')[0]] + [':'.join(msg_decrypted.split(':')[1:])]+[eemsg[2]] else: msg = [None,msg_decrypted,eemsg[2]] his_seq = int(eemsg[0][len('seq:'):]) if his_seq <= tlsn_msg_receiver.last_seq_which_i_acked: #the other side is out of sync, send an ack again mi.send_raw(' :' + counterparty_nick + ' ack:' + str(his_seq)) continue #we did not receive the next seq in order if not his_seq == tlsn_msg_receiver.last_seq_which_i_acked +1: continue #else we got a new seq if len(chunks)==0: #a new message is starting if not msg[0].startswith(message_headers) : continue hdr = msg[0] #'CRLF' is used at the end of the first chunk, 'EOL' is used to show that there are no more chunks chunks.append(msg[1]) mi.send_raw(' :' + counterparty_nick + ' ack:' + str(his_seq)) tlsn_msg_receiver.last_seq_which_i_acked = his_seq if msg[-1]=='EOL': assembled_message = ''.join(chunks) recv_queue.put(hdr+':'+assembled_message) chunks = []
def tlsn_send_raw(data): if not initialized: raise Exception("TLSN Messaging not yet instantiated") return mi.send_raw(data)
def tlsn_msg_receiver(my_nick, counterparty_nick, ack_queue, recv_queue, message_headers, pk, seq_init=100000): '''Intended to be run as a thread; puts msgs sent to my_nick from counterparty_nick onto the Queue recv_queue, and sends acknowledgements onto ack_queue, filtering out messages whose headers/topics are not in message_headers, and using sequence numbering starting from seq_init (or 0 if seq_init is undef). Messages are received in chunks and decrypted using private key pk and base64 decoded, then reassembled according to line endings CRLF and EOL, as per tlsnotary's messaging protocol. ''' if not initialized: raise Exception("TLSN Messaging not yet instantiated") if not hasattr(tlsn_msg_receiver, 'last_seq_which_i_acked'): if not seq_init: seq_init = 0 tlsn_msg_receiver.last_seq_which_i_acked = seq_init #static variable. Initialized only on first function's run chunks = [] while True: eemsg = mi.msg_receiver(my_nick, counterparty_nick) if not eemsg: continue #note that the timeout is in the implementation layer #acknowledgements are not our business here; put them on the queue if eemsg[0].startswith('ack'): #acks are not encrypted ack_queue.put(eemsg[0][len('ack:'):]) continue if len(eemsg) != 3: continue if not eemsg[0].startswith('seq'): continue #wrong format; old server hellos will do this msg_decrypted = dd(eemsg[1], pk) #print ("decrypted message is: ",msg_decrypted) if len(chunks) == 0: msg = [msg_decrypted.split(':')[0] ] + [':'.join(msg_decrypted.split(':')[1:])] + [eemsg[2]] else: msg = [None, msg_decrypted, eemsg[2]] his_seq = int(eemsg[0][len('seq:'):]) if his_seq <= tlsn_msg_receiver.last_seq_which_i_acked: #the other side is out of sync, send an ack again mi.send_raw(' :' + counterparty_nick + ' ack:' + str(his_seq)) continue #we did not receive the next seq in order if not his_seq == tlsn_msg_receiver.last_seq_which_i_acked + 1: continue #else we got a new seq if len(chunks) == 0: #a new message is starting if not msg[0].startswith(message_headers): continue hdr = msg[0] #'CRLF' is used at the end of the first chunk, 'EOL' is used to show that there are no more chunks chunks.append(msg[1]) mi.send_raw(' :' + counterparty_nick + ' ack:' + str(his_seq)) tlsn_msg_receiver.last_seq_which_i_acked = his_seq if msg[-1] == 'EOL': assembled_message = ''.join(chunks) recv_queue.put(hdr + ':' + assembled_message) chunks = []