a lot of work on sockets, and added chat module

master
Kevin Froman 2018-09-19 23:35:26 -05:00
parent 1d7fd65f38
commit f8b10cfe12
6 changed files with 83 additions and 28 deletions

View File

@ -466,8 +466,12 @@ class OnionrCommunicatorDaemon:
self.blockToUpload = cmd[1] self.blockToUpload = cmd[1]
threading.Thread(target=self.uploadBlock).start() threading.Thread(target=self.uploadBlock).start()
elif cmd[0] == 'startSocket': elif cmd[0] == 'startSocket':
# Create a socket or connect to one # Create a socket or connect to one.
self.onionrsockets.append(onionrsockets.OnionrSockets(self._core, startData)) # The socket handler (such as the plugin or app using it) is specified in startData['reason]
startData = json.loads(cmd[1])
rCallback = onionrsockets.getSocketCallbackRecieveHandler(self._core, startData['reason'], startData['create'])
sCallback = onionrsockets.getSocketCallbackSendHandler(self._core, startData['reason'], startData['create'])
self.onionrsockets.append(onionrsockets.OnionrSockets(self._core, startData, recieveCallback=rCallback, sendCallback=sCallback))
else: else:
logger.info('Recieved daemonQueue command:' + cmd[0]) logger.info('Recieved daemonQueue command:' + cmd[0])

View File

@ -21,7 +21,7 @@ import sqlite3, os, sys, time, math, base64, tarfile, getpass, simplecrypt, hash
from onionrblockapi import Block from onionrblockapi import Block
import onionrutils, onionrcrypto, onionrproofs, onionrevents as events, onionrexceptions, onionrvalues import onionrutils, onionrcrypto, onionrproofs, onionrevents as events, onionrexceptions, onionrvalues
import onionrblacklist import onionrblacklist, onionrchat
import dbcreator import dbcreator
if sys.version_info < (3, 6): if sys.version_info < (3, 6):
try: try:
@ -79,6 +79,7 @@ class Core:
# Initialize the crypto object # Initialize the crypto object
self._crypto = onionrcrypto.OnionrCrypto(self) self._crypto = onionrcrypto.OnionrCrypto(self)
self._blacklist = onionrblacklist.OnionrBlackList(self) self._blacklist = onionrblacklist.OnionrBlackList(self)
self.chatInst = onionrchat.OnionrChat(self)
except Exception as error: except Exception as error:
logger.error('Failed to initialize core Onionr library.', error=error) logger.error('Failed to initialize core Onionr library.', error=error)

View File

@ -68,6 +68,7 @@ class NetController:
# Set the Tor control password. Meant to make it harder to manipulate our Tor instance # Set the Tor control password. Meant to make it harder to manipulate our Tor instance
plaintext = base64.b64encode(os.urandom(50)).decode() plaintext = base64.b64encode(os.urandom(50)).decode()
config.set('tor.controlpassword', plaintext, savefile=True) config.set('tor.controlpassword', plaintext, savefile=True)
config.set('tor.socksport', self.socksPort, savefile=True)
controlPort = random.randint(1025, 65535) controlPort = random.randint(1025, 65535)

30
onionr/onionrchat.py Normal file
View File

@ -0,0 +1,30 @@
'''
Onionr - P2P Anonymous Storage Network
Onionr Chat Messages
'''
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
import logger
class OnionrChat:
def __init__(self, coreInst):
return
def recieveMessage(self, socketInst, data):
logger.info('Got %s' % (data,))
return ''
def sendMessage(self, socketInst, data):
return "Hello"

View File

@ -18,13 +18,25 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
''' '''
import stem.control import stem.control
import socket, selectors import socket, selectors, socks, config
import onionrexceptions, time import onionrexceptions, time, onionrchat
from dependencies import secrets from dependencies import secrets
sel = selectors.DefaultSelector() sel = selectors.DefaultSelector()
def getSocketCallbackRecieveHandler(coreInst, reason, create):
'''Return the recieve handler function for a given socket reason'''
retData = ''
if startData == 'chat':
retData = coreInst.chatInst.recieveMessage
def getSocketCallbackSendHandler(coreInst, reason, create):
'''Return the send handler function for a given socket reason'''
retData = ''
if startData == 'chat':
retData = coreInst.chatInst.sendMessage
class OnionrSockets: class OnionrSockets:
def __init__(self, coreInst, socketInfo): def __init__(self, coreInst, socketInfo, recieveCallback=None, sendCallback=None):
'''Create a new Socket object. This interface is named a bit misleadingly '''Create a new Socket object. This interface is named a bit misleadingly
and does not actually forward network requests. and does not actually forward network requests.
@ -36,6 +48,12 @@ class OnionrSockets:
self.socketID = secrets.token_hex(32) # Generate an ID for this socket self.socketID = secrets.token_hex(32) # Generate an ID for this socket
self._core = coreInst self._core = coreInst
self.socketInfo = socketInfo self.socketInfo = socketInfo
if not callable(sendCallback) or not callable(recieveCallback)
raise ValueError("callback must be a function")
self.sendCallback = sendCallback
self.recieveCallback = recieveCallback
# Make sure socketInfo provides all necessary values # Make sure socketInfo provides all necessary values
for i in ('peer', 'address', 'create', 'port'): for i in ('peer', 'address', 'create', 'port'):
@ -50,11 +68,11 @@ class OnionrSockets:
self.socketPort = socketInfo['port'] self.socketPort = socketInfo['port']
self.serverAddress = socketInfo['address'] self.serverAddress = socketInfo['address']
self.connected = False self.connected = False
self.segment = 0
self.connData = {}
if self.isServer: if self.isServer:
self.createServer() self.createServer()
else:
self.connectServer()
def createServer(self): def createServer(self):
# Create our HS and advertise it via a block # Create our HS and advertise it via a block
@ -87,34 +105,31 @@ class OnionrSockets:
callback(key.fileobj, mask) callback(key.fileobj, mask)
return return
def connectServer(self):
return
def _accept(self, sock, mask): def _accept(self, sock, mask):
# Just accept the connection and pass it to our handler # Just accept the connection and pass it to our handler
conn, addr = sock.accept() conn, addr = sock.accept()
conn.setblocking(False) conn.setblocking(False)
sel.register(conn, selectors.EVENT_READ, self._read) sel.register(conn, selectors.EVENT_READ, self._read)
self.connected = True
def _read(self, conn, mask): def _read(self, conn, mask):
data = conn.recv(1000).decode() data = conn.recv(1024)
if data: if data:
self.segment += 1 data = data.decode()
self.connData[self.segment] = data self.callback(self, data)
conn.send(data)
else: else:
sel.unregister(conn) sel.unregister(conn)
conn.close() conn.close()
def readConnection(self): def connectServer(self):
if not self.connected: # Set the Tor proxy
raise Exception("Connection closed") socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, '127.0.0.1', config.get('tor.socksport'), rdns=True)
count = 0 socket.socket = socks.socksocket
while self.connected: remoteSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
yield self.connData[count] with remoteSocket as s:
count += 1 s.connect((self.serverAddress, self.port))
except KeyError: data = s.recv(1024)
pass data.send(self.sendCallback(self, data.decode()))
time.sleep(0.01) return

View File

@ -85,8 +85,12 @@ def on_processBlocks(api):
port = api.data['port'] port = api.data['port']
except KeyError: except KeyError:
raise ValueError("Missing port for new socket") raise ValueError("Missing port for new socket")
try:
reason = api.data['reason']
except KeyError:
raise ValueError("Missing socket reason")
socketInfo = json.dumps({'peer': api.data['signer'], 'address': address, 'port': port, create = False}) socketInfo = json.dumps({'peer': api.data['signer'], 'address': address, 'port': port, 'create' = False, 'reason': reason})
api.get_core().daemonQueueAdd('startSocket', socketInfo) api.get_core().daemonQueueAdd('startSocket', socketInfo)
def on_init(api, data = None): def on_init(api, data = None):