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]
threading.Thread(target=self.uploadBlock).start()
elif cmd[0] == 'startSocket':
# Create a socket or connect to one
self.onionrsockets.append(onionrsockets.OnionrSockets(self._core, startData))
# Create a socket or connect to one.
# 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:
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
import onionrutils, onionrcrypto, onionrproofs, onionrevents as events, onionrexceptions, onionrvalues
import onionrblacklist
import onionrblacklist, onionrchat
import dbcreator
if sys.version_info < (3, 6):
try:
@ -79,6 +79,7 @@ class Core:
# Initialize the crypto object
self._crypto = onionrcrypto.OnionrCrypto(self)
self._blacklist = onionrblacklist.OnionrBlackList(self)
self.chatInst = onionrchat.OnionrChat(self)
except Exception as 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
plaintext = base64.b64encode(os.urandom(50)).decode()
config.set('tor.controlpassword', plaintext, savefile=True)
config.set('tor.socksport', self.socksPort, savefile=True)
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/>.
'''
import stem.control
import socket, selectors
import onionrexceptions, time
import socket, selectors, socks, config
import onionrexceptions, time, onionrchat
from dependencies import secrets
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:
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
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._core = coreInst
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
for i in ('peer', 'address', 'create', 'port'):
@ -50,11 +68,11 @@ class OnionrSockets:
self.socketPort = socketInfo['port']
self.serverAddress = socketInfo['address']
self.connected = False
self.segment = 0
self.connData = {}
if self.isServer:
self.createServer()
else:
self.connectServer()
def createServer(self):
# Create our HS and advertise it via a block
@ -87,34 +105,31 @@ class OnionrSockets:
callback(key.fileobj, mask)
return
def connectServer(self):
return
def _accept(self, sock, mask):
# Just accept the connection and pass it to our handler
conn, addr = sock.accept()
conn.setblocking(False)
sel.register(conn, selectors.EVENT_READ, self._read)
self.connected = True
def _read(self, conn, mask):
data = conn.recv(1000).decode()
data = conn.recv(1024)
if data:
self.segment += 1
self.connData[self.segment] = data
conn.send(data)
data = data.decode()
self.callback(self, data)
else:
sel.unregister(conn)
conn.close()
def readConnection(self):
if not self.connected:
raise Exception("Connection closed")
count = 0
while self.connected:
try:
yield self.connData[count]
count += 1
except KeyError:
pass
time.sleep(0.01)
def connectServer(self):
# Set the Tor proxy
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, '127.0.0.1', config.get('tor.socksport'), rdns=True)
socket.socket = socks.socksocket
remoteSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
with remoteSocket as s:
s.connect((self.serverAddress, self.port))
data = s.recv(1024)
data.send(self.sendCallback(self, data.decode()))
return

View File

@ -85,8 +85,12 @@ def on_processBlocks(api):
port = api.data['port']
except KeyError:
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)
def on_init(api, data = None):