Hi again Kenton!

I finally got around to make the PR (wanted to check it extensively first),
it seems to work well: https://github.com/capnproto/pycapnp/pull/169 - I
think it works more or less like the BootstrapFactory you described earlier.

This also allowed me to find and fix a little (dangerous) shortcut I took
when writing the client - message authorship data was basically sent by
client instead of enforced by server, so clients could spoof names if they
hacked the program or did some packet filtering. I indeed used a room
wrapper for this - the interface is instanced once per client, but the
underlying "data-holding" object is instanced once per room (and passed to
the interface constructor when the client joins a room). As of yet, rooms
don't need to access the client IP, but since they now have a reference to
the client object, they can of course get more than just the name.

I've been using all the knowledge this allowed me to get on capnchat:
https://github.com/Cheaterman/capnchat/ - seems to work fine right now :-)
I'm mostly happy with it (except some visual bugs) and will now move on to
more serious networking things (multiplayer games come to mind as mentioned
:-D).

Quick question: as mentioned, my next PR might be about exposing UDP to
Python. I think the most maintained way to establish a connection in
TwoPartyServer/Client on pycapnp is using connection strings. I was
wondering if you think using udp:// prefix in a connection string sounds
like a nice way to expose this feature to users (since we already have
unix:// for UNIX sockets)? Obviously I'm not asking for a change in Capnp
or the C++ side of TwoPartyServer, I'd just implement it at Python level
and use bindDatagramPort() instead of listen() at C++ level as mentioned
earlier.

Thanks again for all your help, and thanks in advance for your answer ^__^

2018-03-21 17:43 GMT+01:00 The Cheaterman <[email protected]>:

> Hi Kenton!
>
> Thanks for your fantastic answer as usual, I'm sorry I didn't take the
> time to respond yesterday but I was implementing the first thing you
> suggested! I noticed PyCapnp serves the same instance of the bootstrap
> object to all clients (as it is now) so I made the necessary changes to
> both re-instanciate the bootstrap object for every cilent, and call its
> constructor (and a customizable method) with the client host/port as
> arguments, so one can easily track which object is served to which user ;
> although in my case - and possibly many others - I will be serving a
> "login" interface to the client as bootstrap, and then serve another
> capability that will have access to this data as necessary, while tracking
> users and rooms in a singleton as I currently do. Why a singleton? Well, I
> may need, for instance, all logged in users to be able to communicate with
> each other, so I need to keep track of the client capability they send me
> at login and their associated nickname (but I probably don't want to keep
> track of their host/port there) so that I can serve a client capability to
> another user given a username ; or more simply to hold a list of the
> available "rooms" so that I can serve them to my clients as requested.
> (this might not be the right way to do things in capability-based
> environments, so please let me know! I had made an example "new" proto
> here, don't know how good it is yet: https://gist.github.com/Cheaterman/
> 767214e4fd04278e1f1eea11c50a83e7 - Login is the bootstrap, and Server is
> the capability that will have access to its associated client host/port - I
> would wrap its methods just like you suggested with some sort of decorator
> or possibly a motherclass to make everything look nice and pretty!)
>
> I'm going to be cleaning up the commits to PyCapnp I made to have the
> bootstrap class be instanced once per client and have its client host/port
> be passed to constructor and optional callback, I would love if you could
> take a look (I will try to point the relevant locations) to what I did as
> the codebase seems to be based on EzRPC so I imagine (despite some of it
> being Cython) you would have some great insights as to what seems to be
> done right and wrong!
>
> Speaking of PyCapnp PR's, I will probably be implementing UDP support into
> it very soon as well because it seems like it's super simple with KJ? All I
> would need is to call bindDatagramPort() instead of listen() on the
> NetworkAddress it seems, and I feel like I found the right place, so I'm
> going to do that as well relatively soon.
>
> I don't know if I'll be posting the PR tonight (I need to test it more)
> but at least you can get an idea how many things you just set in motion
> with your great answer :-)
>
> Thanks a lot again! I'll keep you in touch about the PR :-)
>
>
>
> 2018-03-20 0:09 GMT+01:00 Kenton Varda <[email protected]>:
>
>> If you've already managed to get the information to your bootstrap
>> object, then the right thing to do from there is to have the bootstrap
>> object add wrappers to other objects which add knowledge of the IP to them.
>>
>> For example:
>>
>>     interface Bootstrap {
>>       getRoom @0 (name :Text) -> (room :Room);
>>     }
>>
>> The getRoom() method might do something like:
>>
>>     getRoom(this, name):
>>       room = rooms.find(name)
>>       return RoomWrapper(room, this.client_ip)
>>
>> RoomWrapper is a class that implements the `Room` RPC interface for a
>> specific client, with knowledge of that client's IP. Whenever it receives
>> an RPC, it can call into the wrapped room object and pass along the IP
>> address as well.
>>
>> This is a common design pattern in Cap'n Proto. Since capnp is
>> capability-based, we like to avoid "ambient authority" (information about
>> the call context that is not expressed in the parameters).
>>
>> As for how the bootstrap interface itself gets the info: In C++ there's a
>> concept of a BootstrapFactory which receives a callback each time a client
>> connects, and receives the identity of the client. I imagine this isn't
>> exposed yet in Python, but this would be the way to do it.
>>
>> -Kenton
>>
>> On Mon, Mar 19, 2018 at 2:59 PM, The Cheaterman <[email protected]
>> > wrote:
>>
>>> Hi everyone, I hope you're doing great!
>>>
>>> As you may already know, I'm doing a small chat system to familiarize
>>> myself with Capnp before I do more ambitious things. I would like to have
>>> some sort of way to implement a banlist on the chat server. I do realize
>>> the whole point of capabilities is to have the same behavior no matter
>>> where the capability is called from. However, I feel like users
>>> (administrators) of server software are used to filter users by IP (when it
>>> comes to that). Alternatively, I'd like to find something unique (but
>>> persistent for a given computer - OS install? hardware? not sure) I could
>>> send during the handshake, to filter undesired users. Basically, I feel
>>> like I need some sort of persistent authentication system that's relatively
>>> hard to refresh, if I can't get access to the IP:port of the user even in
>>> the bootstrap object. I currently managed to hack pycapnp to get a method
>>> called on the bootstrap object when a client connects with IP and port as
>>> arguments, but even if I store them I have no way of knowing which client
>>> calls a given callback (which is a design choice I imagine).
>>>
>>> I'd like to know your thoughts on the subject :-) thanks a lot in
>>> advance!
>>>
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "Cap'n Proto" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to [email protected].
>>> Visit this group at https://groups.google.com/group/capnproto.
>>>
>>
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
Visit this group at https://groups.google.com/group/capnproto.

Reply via email to