[Twisted-Python] Accessing ClientFactory methods?

Brian Warner warner at lothar.com
Mon Jul 14 13:11:05 MDT 2003


> Any other solutions that people have found? I'd like to be able to make
> a single, canonical clean way for doing this.

I'm not sure that a single technique can be found, because the problem is
going to be different for every application.

The Protocol instance represents a single connection to a single client. You
could have dozens of these connections happening at the same time. From
outside the Protocol object, which one do you want to send a message to? Who
is deciding to send a message to them?

I see two general possibilities:

 The connections are like login sessions to a shell. Each one has some state
 that is scoped to the connection (it goes away when the connection is
 dropped). Messages sent out through the connection are triggered by actions
 caused by commands that came in through the same connection. "/bin/ls"
 results in some text being returned.

   In this case, either the state can be stored in the Protocol subclass, or
   in a companion object which is associated at login time (in the
   connectionMade method).

     class echo(Protocol):
         def connectionMade(self):
             self.session = NewSession()
         def dataReceived(self, data):
             # buffer data, look for command, parse it
             self.session.doCommand(command, self)
         def sendMsg(self, data):
             self.transport.write(data)

   In this scheme, each command gets a handle which it can use to send data
   back to the user. You might also want to give that handle to
   NewSession(), so it can send data to the user at any time (think of the
   unix 'write' command). There might be other tables where the Protocol
   reference needs to be added: a list of connections for each username, a
   list of connections for each MUD player who is in a particular room, a
   list of connections using a particular database.

   Finally, you might also want to keep a global list of all connections (to
   implement the unix 'wall' command which sends a message to *everybody*
   logged in):

     class echo(Protocol):
         def connectionMade(self):
             self.factory.allConnections.append(self)
         def connectionLost(self, reason):
             self.factory.allConnections.remove(self)
     class echofactory(Factory):
         allConnections = []
         def broadcastMsg(self, msg):
             for p in self.allConnections:
                 p.sendMsg(msg)

 The other general scheme would be to allow only a single connection at a
 time. This removes the question of "which one do you want to talk to". Then
 you can store the Protocol instance in the Factory, the Application, or
 even as a global.
           
     class echo(Protocol):
         def connectionMade(self):
             global TheConnection
             assert(TheConnection == None)
             TheConnection = self
         def connectionLost(self, reason):
             global TheConnection
             TheConnection = None
     def sendMessage(msg):
         TheConnection.sendMsg(msg)


Thinking about the issue in terms of multiple simultaneous connections and
how do you decide *which* you want to talk to might make it easier to answer
the question of where to store the Protocol reference.

hope that helps,
 -Brian




More information about the Twisted-Python mailing list