a lot of work on sockets, and added chat module
This commit is contained in:
parent
1d7fd65f38
commit
f8b10cfe12
@ -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])
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
30
onionr/onionrchat.py
Normal 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"
|
@ -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
|
@ -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):
|
||||
|
Loading…
Reference in New Issue
Block a user