Skip to content

Instantly share code, notes, and snippets.

@hellais
Created May 17, 2012 16:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hellais/2719870 to your computer and use it in GitHub Desktop.
Save hellais/2719870 to your computer and use it in GitHub Desktop.
Simple Hidden Chat
import tempfile
import functools
import os
from datetime import datetime
from twisted.internet.protocol import Factory
from twisted.internet.endpoints import TCP4ServerEndpoint
from twisted.internet import fdesc
from twisted.protocols.basic import LineReceiver
from twisted.internet import reactor
import txtorcon
class Chat(LineReceiver):
delimiter = "\n"
def __init__(self, users, fp, config):
self.users = users
self.fp = fp
self.config = config
self.name = None
self.private = True
self.state = "GETNAME"
def connectionMade(self):
self.sendLine("What is your name?")
def connectionLost(self, reason):
if self.users.has_key(self.name):
del self.users[self.name]
def lineReceived(self, line):
line = line.strip()
if self.state == "GETNAME":
self.handle_GETNAME(line)
elif self.state == "OPTIONS":
self.handle_OPTIONS(line)
else:
self.handle_CHAT(line)
def handle_GETNAME(self, name):
if name in self.users:
self.sendLine("Name taken, pick another one..")
return
if len(self.users) > 0:
self.sendLine("Currently logged in users: ")
for user, p in self.users.iteritems():
self.sendLine(user)
else:
self.sendLine("There is currently nobody logged in")
self.name = name
self.state = "OPTIONS"
self.sendLine("Do you wish to talk to me privately? (y/n)")
def handle_OPTIONS(self, choice):
if choice.lower() == "y":
self.private = True
elif choice.lower() == "n":
self.private = False
else:
self.sendLine("Sorry I did not understand you.")
return
self.users[self.name] = [self, self.private]
self.sendLine("You may now talk :)")
self.state = "CHAT"
def handle_CHAT(self, message):
if len(message.strip()) == 0:
return
message = "<%s> %s" % (self.name, message)
logmessage = datetime.now().strftime(self.config['dateformat'])
logmessage += " -*- "
if self.private:
logmessage += "(PRIV8) "
logmessage += message + "\n"
self.fp.write(logmessage)
for name, protocol in self.users.iteritems():
if protocol[0] != self and not protocol[1] and not self.private:
protocol[0].sendLine(message)
class ChatFactory(Factory):
def __init__(self, fileName):
self.users = {}
self.file = fileName
self.config = {'dateformat': '%d/%m/%Y %H:%M:%S'}
def startFactory(self):
self.fp = open(self.file, 'a')
self.fp.write("===========================================\n")
self.fp.write("= Chat server started ")
self.fp.write(datetime.now().strftime(self.config['dateformat']))
self.fp.write(" =\n===========================================\n")
def stopFactory(self):
self.fp.close()
def buildProtocol(self, addr):
return Chat(self.users, self.fp, self.config)
def setup_complete(proto):
print "Your chat server is now online!"
global config
onion_address = config.HiddenServices[0].hostname
print "It is running at"
print "%s (port %d)" % (onion_address, hs_public_port)
print "The hidden service directory for it is at:",config.HiddenServices[0].dir
print
print "You should be able to connect to it and chat via:"
print " torsocks nc %s %s" % (onion_address, hs_public_port)
def setup_failed(arg):
print "SETUP FAILED",arg
reactor.stop()
hs_port = 8123
hs_public_port = 1337
hs_dir = os.path.join(os.getcwd(), 'hiddenservice')
config = txtorcon.TorConfig()
config.HiddenServices = [txtorcon.HiddenService(config, hs_dir, [str(hs_public_port) + " 127.0.0.1:"+str(hs_port)])]
config.save()
hs_endpoint = TCP4ServerEndpoint(reactor, hs_port)
hs_endpoint.listen(ChatFactory("chat.log"))
def updates(prog, tag, summary):
print "%d%%: %s" % (prog, summary)
d = txtorcon.launch_tor(config, reactor, progress_updates=updates)
d.addCallback(setup_complete)
d.addErrback(setup_failed)
reactor.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment