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]
|
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])
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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
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/>.
|
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
|
@ -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):
|
||||||
|
Loading…
Reference in New Issue
Block a user