2020-09-06 06:50:23 +00:00
|
|
|
# internal imports
|
|
|
|
import os,sys; sys.path.append(os.path.abspath(os.path.join(os.path.abspath(os.path.join(os.path.dirname(__file__),'..')),'..')))
|
2020-09-29 13:09:56 +00:00
|
|
|
from comrad import *
|
|
|
|
from comrad.backend import *
|
|
|
|
from comrad.backend.phonelines import *
|
|
|
|
from comrad.backend.operators import CALLBACKS
|
2020-09-19 17:51:01 +00:00
|
|
|
import requests
|
2020-09-27 11:32:23 +00:00
|
|
|
from torpy.cell_socket import TorSocketConnectError
|
2020-09-28 12:21:06 +00:00
|
|
|
from requests.exceptions import ConnectionError
|
2020-09-20 06:37:37 +00:00
|
|
|
|
2020-09-14 06:02:17 +00:00
|
|
|
# def TheTelephone(*x,**y):
|
2020-09-29 13:09:56 +00:00
|
|
|
# return Comrad(TELEPHONE_NAME,*x,**y)
|
2020-09-14 06:02:17 +00:00
|
|
|
|
2020-09-06 06:50:23 +00:00
|
|
|
### ACTUAL PHONE CONNECTIONS
|
2020-09-06 19:24:36 +00:00
|
|
|
class TheTelephone(Operator):
|
2020-09-06 06:50:23 +00:00
|
|
|
"""
|
|
|
|
API client class for Caller to interact with The Operator.
|
|
|
|
"""
|
2020-09-19 17:51:01 +00:00
|
|
|
def __init__(self, caller=None, callbacks={}):
|
2020-09-19 18:54:57 +00:00
|
|
|
super().__init__(name=TELEPHONE_NAME,callbacks=callbacks)
|
2020-09-06 22:40:53 +00:00
|
|
|
self.caller=caller
|
2020-09-29 13:09:56 +00:00
|
|
|
from comrad.backend.phonelines import check_phonelines
|
2020-09-12 17:00:06 +00:00
|
|
|
keychain = check_phonelines()[TELEPHONE_NAME]
|
2020-09-13 19:25:43 +00:00
|
|
|
self._keychain ={**self.load_keychain_from_bytes(keychain)}
|
2020-09-19 18:54:57 +00:00
|
|
|
|
|
|
|
self.log(f'Starting up with callbacks: {self._callbacks}')
|
2020-09-09 14:38:37 +00:00
|
|
|
|
2020-09-06 06:50:23 +00:00
|
|
|
|
2020-09-22 14:02:00 +00:00
|
|
|
@property
|
|
|
|
def api_url(self):
|
2020-09-29 13:16:50 +00:00
|
|
|
#if 'COMRAD_OPERATOR_API_URL' in os.environ and os.environ['COMRAD_OPERATOR_API_URL']:
|
2020-09-22 14:02:00 +00:00
|
|
|
# return os.environ
|
2020-09-29 13:16:50 +00:00
|
|
|
#os.environ['COMRAD_OPERATOR_API_URL'] = OPERATOR_API_URL_TOR
|
|
|
|
if 'COMRAD_USE_TOR' in os.environ and os.environ['COMRAD_USE_TOR']=='1':
|
2020-09-22 14:02:00 +00:00
|
|
|
return OPERATOR_API_URL_TOR
|
2020-09-29 13:16:50 +00:00
|
|
|
elif 'COMRAD_USE_CLEARNET' in os.environ and os.environ['COMRAD_USE_CLEARNET']=='1':
|
2020-09-22 14:02:00 +00:00
|
|
|
return OPERATOR_API_URL_CLEARNET
|
|
|
|
else:
|
|
|
|
return OPERATOR_API_URL
|
|
|
|
|
|
|
|
|
2020-09-27 11:32:23 +00:00
|
|
|
async def send_and_receive(self,msg_d,n_attempts=3,**y):
|
2020-09-13 07:54:39 +00:00
|
|
|
# self.log('send and receive got incoming msg:',msg_d)
|
2020-09-13 07:41:12 +00:00
|
|
|
|
2020-09-13 07:54:39 +00:00
|
|
|
# assert that people can speak only with operator in their first enclosed message!
|
|
|
|
# if so, dropping the "to"
|
|
|
|
if msg_d['to'] != self.op.pubkey.data:
|
2020-09-29 16:25:19 +00:00
|
|
|
raise ComradException('Comrades must communicate securely with Operator first.')
|
2020-09-13 07:54:39 +00:00
|
|
|
# opp = Operator(pubkey=msg_d['to'])
|
|
|
|
# self.log('got opp:',opp.pubkey.data == msg_d['to'], self.op.pubkey.data == msg_d['to'])
|
2020-09-13 09:07:08 +00:00
|
|
|
|
2020-09-13 09:08:33 +00:00
|
|
|
# self.log('got msg_d:',msg_d)
|
2020-09-13 09:07:08 +00:00
|
|
|
|
2020-09-13 09:08:33 +00:00
|
|
|
# self.log('but going to send just msg?',msg_b)
|
2020-09-13 07:41:12 +00:00
|
|
|
|
2020-09-12 19:00:33 +00:00
|
|
|
msg_b=msg_d["msg"]
|
|
|
|
msg_b64 = b64encode(msg_b)
|
2020-09-09 15:21:13 +00:00
|
|
|
msg_b64_str = msg_b64.decode()
|
2020-09-13 08:03:02 +00:00
|
|
|
self.log(f'''Sending the encrypted content package:\n\n{msg_b64_str}''')
|
2020-09-10 14:04:32 +00:00
|
|
|
|
2020-09-12 19:00:33 +00:00
|
|
|
# seal for transport
|
|
|
|
msg_b64_str_esc = msg_b64_str.replace('/','_')
|
2020-09-10 14:04:32 +00:00
|
|
|
|
2020-09-09 15:21:13 +00:00
|
|
|
# dial the operator
|
2020-09-22 14:02:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
URL = self.api_url + msg_b64_str_esc + '/'
|
2020-09-06 06:50:23 +00:00
|
|
|
self.log("DIALING THE OPERATOR:",URL)
|
2020-09-22 19:34:03 +00:00
|
|
|
|
2020-09-29 13:09:56 +00:00
|
|
|
# phonecall=await self.comrad_request_async(URL)
|
2020-09-24 10:40:48 +00:00
|
|
|
# import asyncio
|
|
|
|
# loop = asyncio.get_event_loop()
|
2020-09-23 18:47:42 +00:00
|
|
|
texec = ThreadExecutor()
|
|
|
|
|
2020-09-27 11:32:23 +00:00
|
|
|
|
|
|
|
for n_attempt in range(n_attempts):
|
|
|
|
self.log('making first attempt to connect via Tor')
|
|
|
|
try:
|
2020-09-29 13:09:56 +00:00
|
|
|
# phonecall=self.comrad_request(URL)
|
|
|
|
phonecall = await texec(self.comrad_request, URL)
|
2020-09-27 11:32:23 +00:00
|
|
|
break
|
2020-09-28 12:21:06 +00:00
|
|
|
except (TorSocketConnectError,ConnectionError) as e:
|
|
|
|
self.log(f'!! {e} trying again?')
|
2020-09-27 11:32:23 +00:00
|
|
|
pass
|
2020-09-22 19:34:03 +00:00
|
|
|
|
2020-09-09 15:21:13 +00:00
|
|
|
if phonecall.status_code!=200:
|
|
|
|
self.log('!! error in request',phonecall.status_code,phonecall.text)
|
|
|
|
return
|
|
|
|
|
|
|
|
# response back from Operator!
|
2020-09-09 20:25:13 +00:00
|
|
|
resp_msg_b64_str = phonecall.text
|
2020-09-13 10:37:47 +00:00
|
|
|
self.log(f'{self}: Received response from Operator! We got back:\n\n',resp_msg_b64_str)
|
2020-09-09 20:25:13 +00:00
|
|
|
|
|
|
|
resp_msg_b64 = resp_msg_b64_str.encode()
|
|
|
|
resp_msg_b = b64decode(resp_msg_b64)
|
2020-09-13 09:47:30 +00:00
|
|
|
# self.log('resp_msg_b:',resp_msg_b)
|
2020-09-13 08:52:28 +00:00
|
|
|
resp_msg_d = pickle.loads(resp_msg_b)
|
2020-09-13 09:47:30 +00:00
|
|
|
# self.log('unpickled:',resp_msg_d)
|
2020-09-09 20:25:13 +00:00
|
|
|
|
2020-09-09 18:31:36 +00:00
|
|
|
# unseal
|
2020-09-29 13:09:56 +00:00
|
|
|
from comrad.backend.messages import Message
|
2020-09-14 06:02:17 +00:00
|
|
|
resp_msg_obj = Message(resp_msg_d)
|
2020-09-09 22:43:50 +00:00
|
|
|
# res = resp_msg_b_unsealed
|
2020-09-17 18:18:20 +00:00
|
|
|
# self.log('Decoding binary, message discovered:\n',resp_msg_obj)
|
2020-09-09 22:43:50 +00:00
|
|
|
|
2020-09-09 23:01:08 +00:00
|
|
|
# decrypt
|
2020-09-10 08:02:03 +00:00
|
|
|
# resp_msg_obj.decrypt()
|
|
|
|
# self.log('returning decrypted form:',resp_msg_obj)
|
2020-09-09 22:57:52 +00:00
|
|
|
|
|
|
|
return resp_msg_obj
|
2020-09-09 22:50:22 +00:00
|
|
|
# return self.pronto_pronto(resp_msg_obj)
|
2020-09-09 15:21:13 +00:00
|
|
|
|
2020-09-07 11:23:10 +00:00
|
|
|
|
2020-09-22 19:34:03 +00:00
|
|
|
async def ring_ring(self,msg,**y):
|
|
|
|
return await super().ring_ring(
|
2020-09-09 14:38:37 +00:00
|
|
|
msg,
|
|
|
|
to_whom=self.op,
|
2020-09-12 14:32:03 +00:00
|
|
|
get_resp_from=self.send_and_receive,
|
|
|
|
**y
|
2020-09-08 11:23:41 +00:00
|
|
|
)
|
2020-09-19 17:51:01 +00:00
|
|
|
|
|
|
|
### Requests functionality
|
2020-09-29 13:09:56 +00:00
|
|
|
def comrad_request(self,url,allow_clearnet = ALLOW_CLEARNET):
|
2020-09-19 17:51:01 +00:00
|
|
|
if '.onion' in url or not allow_clearnet:
|
|
|
|
return self.tor_request(url)
|
2020-09-29 18:15:46 +00:00
|
|
|
return requests.get(url,timeout=60)
|
2020-09-19 17:51:01 +00:00
|
|
|
|
2020-09-29 13:09:56 +00:00
|
|
|
async def comrad_request_async(self,url,allow_clearnet=ALLOW_CLEARNET):
|
2020-09-22 19:34:03 +00:00
|
|
|
import requests_async as requests
|
|
|
|
if '.onion' in url or not allow_clearnet:
|
|
|
|
return await self.tor_request_async(url)
|
2020-09-29 18:15:46 +00:00
|
|
|
return await requests.get(url,timeout=60)
|
2020-09-22 19:34:03 +00:00
|
|
|
|
|
|
|
|
2020-09-19 17:51:01 +00:00
|
|
|
def tor_request(self,url):
|
2020-09-19 18:54:57 +00:00
|
|
|
return self.tor_request_in_python(url)
|
2020-09-19 17:51:01 +00:00
|
|
|
# return tor_request_in_proxy(url)
|
|
|
|
|
|
|
|
async def tor_request_async(self,url):
|
2020-09-19 18:54:57 +00:00
|
|
|
return await self.tor_request_in_python_async(url)
|
2020-09-19 17:51:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
def tor_request_in_proxy(self,url):
|
2020-09-19 18:54:57 +00:00
|
|
|
with self.get_tor_proxy_session() as s:
|
2020-09-23 18:47:42 +00:00
|
|
|
return s.get(url,timeout=600)
|
2020-09-19 17:51:01 +00:00
|
|
|
|
|
|
|
async def tor_request_in_python_async(self,url):
|
2020-09-23 18:47:42 +00:00
|
|
|
import requests_async
|
2020-09-22 19:34:03 +00:00
|
|
|
tor = TorClient()
|
2020-09-19 17:51:01 +00:00
|
|
|
with tor.get_guard() as guard:
|
|
|
|
adapter = TorHttpAdapter(guard, 3, retries=RETRIES)
|
|
|
|
|
2020-09-23 18:47:42 +00:00
|
|
|
async with requests_async.Session() as s:
|
2020-09-19 17:51:01 +00:00
|
|
|
s.headers.update({'User-Agent': 'Mozilla/5.0'})
|
|
|
|
s.mount('http://', adapter)
|
|
|
|
s.mount('https://', adapter)
|
2020-09-23 18:47:42 +00:00
|
|
|
r = s.get(url, timeout=600)
|
2020-09-22 19:34:03 +00:00
|
|
|
self.log('<-- r',r)
|
|
|
|
return r
|
2020-09-19 17:51:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
def tor_request_in_python(self,url):
|
2020-09-20 06:37:37 +00:00
|
|
|
tor = TorClient()
|
2020-09-19 17:51:01 +00:00
|
|
|
with tor.get_guard() as guard:
|
2020-09-20 06:37:37 +00:00
|
|
|
adapter = TorHttpAdapter(guard, 3, retries=RETRIES)
|
2020-09-19 17:51:01 +00:00
|
|
|
|
|
|
|
with requests.Session() as s:
|
|
|
|
s.headers.update({'User-Agent': 'Mozilla/5.0'})
|
|
|
|
s.mount('http://', adapter)
|
|
|
|
s.mount('https://', adapter)
|
2020-09-23 18:47:42 +00:00
|
|
|
r = s.get(url, timeout=600)
|
2020-09-19 17:51:01 +00:00
|
|
|
return r
|
|
|
|
|
|
|
|
def get_tor_proxy_session(self):
|
|
|
|
session = requests.session()
|
|
|
|
# Tor uses the 9050 port as the default socks port
|
|
|
|
session.proxies = {'http': 'socks5://127.0.0.1:9050',
|
|
|
|
'https': 'socks5://127.0.0.1:9050'}
|
|
|
|
return session
|
|
|
|
|
|
|
|
def get_async_tor_proxy_session(self):
|
|
|
|
import requests_futures
|
|
|
|
from requests_futures.sessions import FuturesSession
|
|
|
|
session = FuturesSession()
|
|
|
|
# Tor uses the 9050 port as the default socks port
|
|
|
|
session.proxies = {'http': 'socks5://127.0.0.1:9050',
|
|
|
|
'https': 'socks5://127.0.0.1:9050'}
|
|
|
|
return session
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-09-09 14:38:37 +00:00
|
|
|
|
2020-09-06 06:50:23 +00:00
|
|
|
|
|
|
|
def test_call():
|
2020-09-08 15:14:48 +00:00
|
|
|
phone = TheTelephone()
|
|
|
|
|
2020-09-12 17:00:06 +00:00
|
|
|
pprint(phone.keychain())
|
|
|
|
|
2020-09-08 15:14:48 +00:00
|
|
|
|
|
|
|
# caller = Caller('marx33') #Caller('marx')
|
2020-09-06 06:50:23 +00:00
|
|
|
# caller.boot(create=True)
|
|
|
|
# print(caller.keychain())
|
2020-09-06 19:59:14 +00:00
|
|
|
# phone = TheTelephone()
|
2020-09-09 18:31:36 +00:00
|
|
|
# req_json = {'_route':'forge_new_keys','name':name, 'pubkey_is_public':pubkey_is_public}}
|
2020-09-06 08:39:31 +00:00
|
|
|
# req_json_s = jsonify(req_json)
|
|
|
|
# res = phone.req({'forge_new_keys':{'name':'marx', 'pubkey_is_public':True}})
|
|
|
|
# print(res)
|
2020-09-07 07:41:17 +00:00
|
|
|
# asyncio.run(caller.get_new_keys())
|
2020-09-08 15:14:48 +00:00
|
|
|
# x=caller.get_new_keys(passphrase='1869')
|
2020-09-06 06:50:23 +00:00
|
|
|
|
2020-09-08 15:14:48 +00:00
|
|
|
# print('YEAH COOL',x)
|
2020-09-06 11:48:35 +00:00
|
|
|
|
2020-09-06 06:50:23 +00:00
|
|
|
## main
|
|
|
|
if __name__=='__main__': test_call()
|