Question

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()
Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top