-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathclient.py
More file actions
executable file
·159 lines (134 loc) · 4.95 KB
/
Copy pathclient.py
File metadata and controls
executable file
·159 lines (134 loc) · 4.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#!/usr/bin/python3.6
"""Usage: python client.py <name> <email>"""
import socket
import config
import sys
import identity
import message
import request
from request import RequestType
import json
import time
import mcrypto
class Client:
def __init__(self, cfg, identifier):
conn = cfg['connection']
self._address = (conn['address'], conn['port'])
self._socket = None
self._msg_size = cfg['message']['size']
self._id = identifier
self._privkey = None
self._target_pubkey = None
def send(self, text, target, wait_for_response=False):
try:
if self._target_pubkey is None:
raise RuntimeError('Target public key not obtained before!')
text = mcrypto.encrypt(text, self._target_pubkey)
msg = message.Message(self._id, target, text)
req = request.Request(RequestType.SEND_MSG, msg)
self._open_socket()
self._socket.connect(self._address)
self._socket.send(str(req).encode())
if wait_for_response:
resp = self.get_response()
self._close_socket()
return resp
except socket.error as err:
print('Error {}: {}'.format(err.errno, err.strerror))
except (KeyboardInterrupt, SystemExit):
pass
finally:
self._close_socket()
return None
def get_response(self):
return self._socket.recv(self._msg_size).decode()
def get_conversation(self, target_id):
resp = None
try:
self._open_socket()
self._socket.connect(self._address)
content = {
'requester': str(self._id),
}
if self._privkey is None:
req = request.Request(RequestType.RECEIVE_PRIVKEY, json.dumps(content))
self._socket.send(str(req).encode())
self._privkey = self.get_response()
content['interlocutor'] = str(target_id)
if self._target_pubkey is None:
req = request.Request(RequestType.RECEIVE_PUBKEY, json.dumps(content))
self._socket.send(str(req).encode())
self._target_pubkey = self.get_response()
req = request.Request(RequestType.RECEIVE_MSGS, json.dumps(content))
self._socket.send(str(req).encode())
resp = self.get_response()
except socket.error as err:
print('Error {}: {}'.format(err.errno, err.strerror))
except (KeyboardInterrupt, SystemExit):
pass
finally:
self._close_socket()
if resp is None or self._privkey is None:
return None
conversation = sorted(json.loads(resp), key=lambda c: c['timestamp'], reverse=False)
for m in conversation:
m['message'] = mcrypto.decrypt(m['message'], self._privkey)
return conversation
def _open_socket(self):
self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def _close_socket(self):
if self._socket:
self._socket.close()
@property
def id(self):
return self._id
if __name__ == "__main__":
if len(sys.argv) < 3:
print(__doc__)
sys.exit(1)
def get_target_id(prompt):
target_name = ''
while target_name == '':
sys.stdout.write('{} name: '.format(prompt))
sys.stdout.flush()
target_name = sys.stdin.readline().strip()
target_email = ''
while target_email == '':
sys.stdout.write('{} email: '.format(prompt))
sys.stdout.flush()
target_email = sys.stdin.readline().strip()
return identity.Identity(target_name, target_email)
def get_message(prompt, forced=True):
msg = ''
while msg == '':
sys.stdout.write('{}: '.format(prompt))
sys.stdout.flush()
msg = sys.stdin.readline().strip()
if forced and msg == '':
continue
return msg
def get_conversation(client, target_id):
conversation = client.get_conversation(target_id)
if conversation is None:
return
for m in conversation:
current_time = time.ctime(m['timestamp'])
sender = identity.Identity.create(m['sender'])
content = m['message']
print('{} {:>15}: {}'.format(current_time, sender.name if sender.name != client.id.name else 'Me', content))
def chat(client):
target_id = get_target_id('Interlocutor')
while True:
get_conversation(client, target_id)
msg = get_message('$', False)
if msg == '':
continue
client.send(msg, target_id, True)
cid = identity.Identity(sys.argv[1], sys.argv[2])
conf = config.load()
c = Client(conf, cid)
while True:
try:
chat(c)
except (KeyboardInterrupt, SystemExit):
break