<br><br><div><span class="gmail_quote">On 11/24/06, <b class="gmail_sendername">Phil Christensen</b> &lt;<a href="mailto:phil@bubblehouse.org">phil@bubblehouse.org</a>&gt; wrote:</span><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
The place where you want to do all this is really in your Realm<br>instance. I think it's possible to create a PB server that doesn't<br>require login, but I've never had any need for it, so you're kind of<br>on your own there.
</blockquote><div><br>Hi Phil,<br>Thanks for the reply.&nbsp; My implementation is very similar to what you described below.&nbsp; I am having the clients pass in a 'mind' object that's representative of them, which is good enough to keep track of some information.&nbsp; What I am having trouble with is getting access to the clients IP address.&nbsp; This is not something I can pass in in the PBClientFactory's login method, since many computers are NAT'ed.&nbsp; 
<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">&gt; class MyRealm:<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; &quot;&quot;&quot;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; Holds a reference to the main service object.
<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; &quot;&quot;&quot;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; __implements__ = portal.IRealm<br>&gt;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; def __init__(self, service):<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;&quot;&quot;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Create a realm with the given service.<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;&quot;&quot;
<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.service = service<br>&gt;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; def requestAvatar(self, avatarId, mind, *interfaces):<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;&quot;&quot;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This function is called after the user has verified their
<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; identity. It returns an object that represents the user<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; in the system, i.e., an avatar.<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;&quot;&quot;<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if pb.IPerspective in interfaces:<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; avatar = self._getPBAvatar(avatarId, mind)
<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ####################### &lt;-- RIGHT HERE<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return pb.IPerspective, avatar, avatar.logout<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else:<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raise NotImplementedError(&quot;no interface&quot;)
<br><br>This is where you want to maintain your client list. The hardest part<br>is deciding on a place to put it that will be accessible from all<br>your code; I usually use a singleton pattern of some kind, where I<br>can import a module that holds onto client references and provides
<br>functions to manipulate/retrieve that list.</blockquote><div><br>Yes, this is something I do have trouble with.&nbsp; I will look into the singleton pattern.&nbsp; It would be nicer if there was a convenient way to bubble up the&nbsp; list of clients.&nbsp;  
<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">So, that point where I put all those hashes is a pretty good place to<br>add clients your client queue. The 'mind' argument is usually a
<br>reference to the client on the other end, assuming your client passes<br>it properly. My client does this:<br><br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; # self.client is a Referenceable on the client side.<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; defer = self.factory.login(credentials.UsernamePassword
<br>&gt; (username, password), self.client)<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; defer.addCallback(connected_callback, self)</blockquote><div><br>I do the same thing. <br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br><br>There's a lot of flexibility there. You could move the<br>clienttracker.append call right inside your Avatar constructor -- the<br>only reason I didn't is because my server supports a number of<br>protocols besides PB, and I wanted to deal with them universally.
<br><br>One thing this approach doesn't do is keep track of clients that<br>connect, but fail authentication. To do that, you'd need to subclass<br>Broker, but that's a tough one. I looked into this once before, and<br>it certainly appears doable -- in the end, a Broker is still a
<br>Protocol, which means it has a transport property you can get client<br>addresses out of.</blockquote><div><br>This is exactly what I need to do so I can associate a client with both their username and ip address.&nbsp; I have access to the broker if I subclass PBServerFactory, but I am not sure how to access it from the Realm, or if it is possible at all.&nbsp;  
<br><br>Any suggestions would be appreciated!<br><br>Thanks,<br>Yi<br></div></div><br>