I've been playing around with the Twisted extension and have fooled around with a chat room sort of system. However I want to expand upon it. As of now it only support multi-client chats with usernames ect. But I want to try and use the pyAudio extension to build a sort of VoIP application. I have a clientFactory and a simple echo protocol in the client and a serverFactory and protocol on the server. but I'm not entirely sure how to build off of this. What would be the best way to go about doing something like this?
Code to help if you need it client.py:
import wx
from twisted.internet import wxreactor
wxreactor.install()
# import twisted reactor
import sys
from twisted.internet import reactor, protocol, task
from twisted.protocols import basic
class ChatFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, parent=None, title="WhiteNOISE")
self.protocol = None # twisted Protocol
sizer = wx.BoxSizer(wx.VERTICAL)
self.text = wx.TextCtrl(self, style=wx.TE_MULTILINE | wx.TE_READONLY)
self.ctrl = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER, size=(300, 25))
sizer.Add(self.text, 5, wx.EXPAND)
sizer.Add(self.ctrl, 0, wx.EXPAND)
self.SetSizer(sizer)
self.ctrl.Bind(wx.EVT_TEXT_ENTER, self.send)
def send(self, evt):
self.protocol.sendLine(str(self.ctrl.GetValue()))
self.ctrl.SetValue("")
class DataForwardingProtocol(basic.LineReceiver):
def __init__(self):
self.output = None
def dataReceived(self, data):
gui = self.factory.gui
gui.protocol = self
if gui:
val = gui.text.GetValue()
gui.text.SetValue(val + data)
gui.text.SetInsertionPointEnd()
def connectionMade(self):
self.output = self.factory.gui.text # redirect Twisted's output
class ChatFactory(protocol.ClientFactory):
def __init__(self, gui):
self.gui = gui
self.protocol = DataForwardingProtocol
def clientConnectionLost(self, transport, reason):
reactor.stop()
def clientConnectionFailed(self, transport, reason):
reactor.stop()
if __name__ == '__main__':
app = wx.App(False)
frame = ChatFrame()
frame.Show()
reactor.registerWxApp(app)
reactor.connectTCP("192.168.1.115", 5001, ChatFactory(frame))
reactor.run()
server.py:
from twisted.internet import reactor, protocol
from twisted.protocols import basic
import time
def t():
return "["+ time.strftime("%H:%M:%S") +"] "
class EchoProtocol(basic.LineReceiver):
name = "Unnamed"
def connectionMade(self):
#on client connection made
self.sendLine("WhiteNOISE")
self.sendLine("Enter A Username Below...")
self.sendLine("")
self.count = 0
self.factory.clients.append(self)
print t() + "+ Connection from: "+ self.transport.getPeer().host
def connectionLost(self, reason):
#on client connection lost
self.sendMsg("- %s left." % self.name)
print t() + "- Connection lost: "+ self.name
self.factory.clients.remove(self)
def lineReceived(self, line):
#actions to do on message recive
if line == '/quit':
#close client connection
self.sendLine("Goodbye.")
self.transport.loseConnection()
return
elif line == "/userlist":
#send user list to single client, the one who requested it
self.chatters()
return
elif line.startswith("/me"):
#send an action formatted message
self.sendLine("**" + self.name + ": " + line.replace("/me",""))
return
elif line == "/?":
self.sendLine("Commands: /? /me /userlist /quit")
return
if not self.count:
self.username(line)
else:
self.sendMsg(self.name +": " + line)
def username(self, line):
#check if username already in use
for x in self.factory.clients:
if x.name == line:
self.sendLine("This username is taken; please choose another")
return
self.name = line
self.chatters()
self.sendLine("You have been connected!")
self.sendLine("")
self.count += 1
self.sendMsg("+ %s joined." % self.name)
print '%s~ %s connected as: %s' % (t(), self.transport.getPeer().host, self.name)
def chatters(self):
x = len(self.factory.clients) - 1
s = 'is' if x == 1 else 'are'
p = 'person' if x == 1 else 'people'
self.sendLine("There %s %i other %s connected:" % (s, x, p) )
for client in self.factory.clients:
if client is not self:
self.sendLine(client.name)
self.sendLine("")
def sendMsg(self, message):
#send message to all clients
for client in self.factory.clients:
client.sendLine(t() + message)
class EchoServerFactory(protocol.ServerFactory):
protocol = EchoProtocol
clients = []
if __name__ == "__main__":
reactor.listenTCP(5001, EchoServerFactory())
reactor.run()
Take a look at Divmod Sine, a SIP application server. The basic idea is that you need an additional network server in your application that will support the VoIP parts of the application.