Re: [capnproto] Protocol "disembargo" message

2022-12-26 Thread Jens Alfke


> On Dec 26, 2022, at 3:28 PM, Kenton Varda  wrote:
> 
>  I'm not sure what you mean about "(negative) remote capability #". There are 
> no negative numbers. 

Oops, I got that from the old E documentation (erights.org.) They used negative 
numbers to identify capability IDs that were created on the “other side” of the 
connection, i.e. promises.

(Speaking of which, is there any other good reading material on 
capabilities-with-RPC, besides erights.org and your own rpc.capnp?)

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/78B9153A-CCA2-4BEE-A628-E46CE039E286%40mooseyard.com.


Re: [capnproto] Protocol "disembargo" message

2022-12-26 Thread Jens Alfke


> On Dec 17, 2022, at 1:46 PM, Kenton Varda  wrote:
> 
> To clarify, when I say "Carol lives in Vat A, i.e. next to Alice", I am 
> saying that Alice and Carol are two objects living in the same process. So a 
> capability pointing to Carol was passed across the network and then back 
> again, over the same connection. 

Thanks. I then spent some time trying to figure out why this scenario occurs — 
when the local peer received the capability Carol from the remote one, 
shouldn’t it have been marked in the protocol as being a peer exported by the 
recipient?

I think this can happen as follows; is this correct?

0. I’ve already sent the capability Carol to the remote peer earlier in the 
connection, so the peer has a reference to Carol.
1. I send an RPC call to acquire a remote capability, and allocate a (negative) 
remote capability # to it. Call it X. (I think this is what the protocol calls 
a promise?)
2. Before the response arrives, I pipeline some more RPC calls addressed to X.
3. I get a response to the first RPC call, identifying X as my capability Carol.

At this point I can remap X to point to Carol, but I’ve already got some 
messages in flight addressed to remote capability X. I assume what happens to 
these is the peer just sends them back to me, substituting Carol for X, and 
then forwards my reply back to me? Thus the problem that I might send local 
messages to Carol that would arrive before the echoed messages to X even though 
I sent them later.

A different architectural solution to this problem might be for a peer to 
reject an incoming request addressed to a capability that isn’t local. Instead 
it would return an error indicating “X isn’t mine, it’s your Carol, so forward 
it there”.

But either way, isn’t there still a race condition if, in a new step 2.5, I 
send a message to local Carol? This message was sent after the message to X but 
arrives before I discover X is Carol, so it’s received out of order.

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/CAD166FA-FF9E-4496-B127-2F226C58307C%40mooseyard.com.


[capnproto] Protocol "disembargo" message

2022-12-17 Thread Jens Alfke
As I peruse the RPC spec (rpc.capnp), I’m following along pretty well until I 
hit the ‘disembargo’ message (which my spellchecker keeps changing into 
‘disembark’, but that’s another matter.)

At this point I’m only interested in Level 1 functionality, two peers, which 
AFAIK is as far as the implementation is gotten.Disembargo is a level 1 
message, and I’m having some trouble understanding it, partly because it seems 
to only be relevant at levels 2+. The description starts on line 660:

>   # Message sent to indicate that an embargo on a recently-resolved promise 
> may now be lifted.
>   #
>   # Embargos are used to enforce E-order in the presence of promise 
> resolution.  That is, if an
>   # application makes two calls foo() and bar() on the same capability 
> reference, in that order,
>   # the calls should be delivered in the order in which they were made.  But 
> if foo() is called
>   # on a promise, and that promise happens to resolve before bar() is called, 
> then the two calls
>   # may travel different paths over the network, and thus could arrive in the 
> wrong order.  In
>   # this case, the call to `bar()` must be embargoed, and a `Disembargo` 
> message must be sent along
>   # the same path as `foo()` to ensure that the `Disembargo` arrives after 
> `foo()`.  Once the
>   # `Disembargo` arrives, `bar()` can then be delivered.


I was following along OK until “the two calls may travel different paths over 
the network.” We’re at Level 1, so there is only one path, the socket between 
peer A and peer B.

Also, in "that promise happens to resolve before bar() is called”, should that 
be "after bar() is called”? Because if foo resolves before, why would that make 
the foo call arrive after the bar call?

If you have time, Kenton, I’d love to see the " Carol lives in Vat A, i.e. next 
to Alice.  In this case, Vat A needs to send a `Disembargo` message that echos 
through Vat B and back…” scenario broken down step-by-step. (Or if this 
situation is discussed in the old erights.org site, let me know the URL; I 
didn’t see it when I was reading through their protocol docs.)

Thanks!

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/E3F6C227-23BD-41E9-A4BA-A93EE4586C49%40mooseyard.com.


[capnproto] RPC protocol framing details?

2022-12-16 Thread Jens Alfke
The RPC docs say:

> The Cap'n Proto RPC protocol is defined in terms of Cap'n Proto serialization 
> schemas. The documentation is inline. See rpc.capnp.

That interface definition is beautifully commented, it’s practically Literate 
Programming, but it’s not the whole story. How are the messages (serialized 
structs) sent over the wire? Is it as simple as just writing one serialized 
buffer after another to a byte-stream, or is there an underlying framing 
protocol?

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/D26CD0E2-861D-4EA5-868F-CBDB109C%40mooseyard.com.


Re: [capnproto] Server process stops accepting connections

2022-11-09 Thread Jens Alfke

> On Nov 9, 2022, at 6:47 AM, 'Kenton Varda' via Cap'n Proto 
>  wrote:
> 
> Have you tested whether your server is able to accept concurrent connections 
> normally? E.g. if you open a connection with telnet or something without 
> sending any bytes, leave that open, and then try to use your server, does it 
> work?

Thanks! That was indeed the problem. The telnet test showed my server would 
accept multiple connections at once, but would only authenticate one of them at 
a time, so a client that didn’t send the right handshake would block others. 

(I’m using custom code, largely copied from rpc.c++ and tls.c++, but 
substituting the SecretHandshake protocol (from Scuttlebutt) for TLS. When I 
adapted TlsConnectionReceiver::acceptLoop, I got things in the wrong order, so 
the tail-recursion back to acceptLoop didn’t occur until the secure handshake 
finished.)

I’ve fixed it now. Next question: if I want to run client connections on 
multiple threads, I presume that after the accept-and-handshake finishes, I 
would create a new thread with an event loop, then use an Executor to pass the 
AsyncIoStream to it, and then do the magic RPC setup on that thread. On 
disconnect I’d either exit the thread or return it to a pool for reuse. Most of 
this seems like boilerplate … are there any working examples I could steal from?

(Why would I want multiple threads when CapnP is async? Because my actual RPC 
methods do SQLite queries, which are blocking and sometimes slow, and I’d 
rather not create async wrappers for my entire complicated database API.)

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/8A947B79-0997-4DEB-9A9A-3EF7B0ACB024%40mooseyard.com.


[capnproto] Server process stops accepting connections

2022-11-08 Thread Jens Alfke
I’ve got a CapnP-based server program running on a Raspberry Pi 4. It’s written 
in C++, using CapnP 0.9.1. It’s single-threaded; the main() function just sets 
up a listener, calls kj::NEVER_DONE.wait, and stays there.

It works fine, except that every few weeks it stops accepting connections; it 
either doesn’t accept the incoming socket at all or never reads from it, I 
can’t tell which; all I see is that the client times out and gives up after 15 
seconds. Then I have to kill and relaunch the server, after which it works fine 
again for a while.

The server process itself isn’t hung; it’s in epoll waiting for events. I 
attached gdb and got this backtrace:
#0  0xb6b8563c in epoll_wait (epfd=7, events=0xbecb4210, maxevents=16,  
timeout=-1)
#1  0x0052edcc in kj::UnixEventPort::doEpollWait (this=0x1fed420, timeout=-1)
#2  0x0052e58c in kj::UnixEventPort::wait (this=0x1fed420)
#3  0x00487744 in kj::EventLoop::wait (this=0x1fed4e0)
#4  0x00488460 in kj::_::waitImpl (node=..., result=..., waitScope=…)
#5  0x00488bd8 in kj::_::NeverDone::wait (this=0x72d3c0 ,  
waitScope=…)
…

The last line in the log shows that it received a connection from some unknown 
IPv4 address which geolocates to Russia (this happens a few times a day; the 
server’s on my home LAN but exposes a public port and I assume these are random 
hackers looking for vulns.) This connection never did anything, not 
surprisingly since I doubt hackers are expecting anything other than HTTP, but 
the logs show the socket never closed. And sure enough, if I run `lsof` I see 
an open TCP port from that address. (Which has been open for at least 24 hours, 
strangely; doesn’t the disconnect idle TCP connections after 90 minutes?)

I’m not sure what to do about this. I assume CapnP is capable of handling 
multiple incoming connections, so this idle socket won’t block others from 
connecting, right? But if not, then why isn’t it accepting any connections?

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/008DEC56-3B4D-4CF7-BFC3-5BECC13BE502%40mooseyard.com.


Re: [capnproto] Text blob too big.

2022-10-31 Thread Jens Alfke


> On Oct 31, 2022, at 12:21 PM, Josemi  wrote:
> 
> Hello.
> 
> I need to work with a structured data that have atributes with undefined 
> lenght, some of them could have GB. 

Most structured storage is optimized for smaller data. And huge values in-line 
push all the records far apart, which is bad for cache performance.

SQLite supports arbitrary size blobs up to 2^64 bytes. (Even with that it’s 
best to put the blobs in a separate table and join your records to it.)

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/1DAB34A2-38DA-4159-A46E-10744D6DED80%40mooseyard.com.


Re: [capnproto] [Request] Error fix consult

2022-09-18 Thread Jens Alfke
The error portion of that lengthy log is:

[ TEST ] kj/async-test.c++:740: legacy test: Async/LargeTaskSetDestruction  

 
*** Received signal #10: Bus error: 10  

 
stack:  

 
FAIL: capnp-test

 
Randomly testing backwards-compatibility scenarios with seed: 1663306371

 

Looks like this was running on macOS.

—Jens


> On Sep 15, 2022, at 10:40 PM, Kukkai W  wrote:
> 
> Dear All,
> 
> I would like to use your capnproto-c version 0.9.1.
> But I run the command "make -j6 check". Error was occurred and it told me to 
> report it to you. Please see the error on the attached file.
> Could you suggest how to fix this?

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/8E3663A9-C455-4C43-8CBE-28CF49FF796E%40mooseyard.com.


Re: [capnproto] Promise destructed while it’s being processed

2022-09-04 Thread Jens Alfke


> On Sep 4, 2022, at 1:08 PM, 'Kenton Varda' via Cap'n Proto 
>  wrote:
> 
> - You say you can't put the promise in a TaskSet because you need to be able 
> to specifically cancel it. Could you instead use a kj::Canceler to control 
> cancellation? The canceler only wraps the promise, then you could still put 
> it in a TaskSet.

This works, thanks; and I already have a TaskSet to put it into. The only nit 
is that the TaskSet’s ErrorHandler gets called with an exception. I suppose I 
can use a separate TaskSet just for the idle timer, with an ErrorHandler whose 
taskFailed method does nothing.

This does seem like a lot of complexity just to implement a cancelable one-shot 
timer...

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/83AA81A6-153A-4660-ADAD-83D47706890A%40mooseyard.com.


[capnproto] Promise destructed while it’s being processed

2022-09-04 Thread Jens Alfke
I’m having some trouble with a Promise stored in a member variable, where the 
’then’ block attached to the promise calls code that ends up clearing that 
variable. This then triggers a kj exception that a Promise is being destructed 
while it’s being processed. I understand why this is an error, but I can’t 
figure out how else to clean up that variable.

The situation is like:
std::optional> _promise;  // This is a data member of my 
class

// In a method of my class:
_promise = something.then([=] {
…do the work…
_promise.clear();   // <— boom
});
How can I make sure _promise is cleared after its handler completes?

I need a specific reference to the promise — I can’t just shove it into a 
TaskSet — because I have code in other methods that clears _promise when it 
decides that it’s no longer needed. (Specifically, this is an idle timer, so 
when an action occurs it needs to clear the timer.)

I can think of a few ways to fix this, but they feel like hacks. I get the 
feeling this is a situation that comes up in various circumstances — a promise 
whose resolution has to clear the Promise variable. Is there a more established 
best practice for handling it?

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/8CC19E73-C543-4689-ABA9-5D612D98C026%40mooseyard.com.


Re: [capnproto] Xcode hits SIGUSR1 signal when I use an Executor

2022-08-31 Thread Jens Alfke



> On Aug 30, 2022, at 7:37 PM, 'Kenton Varda' via Cap'n Proto 
>  wrote:
> 
> Hi Jens,
> 
> It sounds very obnoxious that your debugger insists on breaking on this 
> signal. 

I’ve filed a bug report with Apple.

> With that said, you could try compiling with `-DKJ_USE_PIPE_FOR_WAKEUP`, 
> which causes it to avoid using signals for this. You need to compile both KJ 
> itself and your own code that depends on it with this define; if they don't 
> match you may get undefined behavior.

For posterity: since I’m building with CMake, I accomplished this by adding 
`add_compile_definitions(KJ_USE_PIPE_FOR_WAKEUP)` to my top-level 
CMakeLists.txt, above the line `add_subdirectory(vendor/capnproto)`.

Now my code can talk inter-thread RPC over the fake socket! Yay!

But of course there’s always another roadblock. The next one I hit is a fatal 
exception "expected !loop.running; wait() is not allowed from within event 
callbacks.” Apparently code running in an Executor block on the target thread 
is not allowed to call Promise.wait()? This is a bummer, as so far I’ve been 
lazy and written my RPC client code in blocking style. Looks like it’s time to 
fully async-ify it.

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/6A1BA18F-C625-4486-8A71-166D2E6A9268%40mooseyard.com.


Re: [capnproto] Xcode hits SIGUSR1 signal when I use an Executor

2022-08-30 Thread Jens Alfke
TL;DR: Can the two streams created by kj::newTwoWayPipe() be used on different 
threads? It kind of appears not. 

I’ve found a workaround, the LLDB command
process handle --stop false SIGUSR1
Unfortunately adding it to my .lldbrc file does nothing; I have to enter it by 
hand every time I start the process.

The next roadblock is that my unit tests create a client and a server object, 
then connect them together by calling kj::newTwoWayPipe() and giving one end of 
the pipe to each. This worked fine in a single thread. However, now one end (an 
AsyncIoStream) gets passed into the new background thread where the client 
object lives. I get an exception
"expected threadLocalEventLoop ==  || threadLocalEventLoop == 
nullptr; Event armed from different thread than it was created in.  You must 
use Executor to queue events cross-thread.”

>From this and the backtrace it looks as though when I write to this end of the 
>pipe, it wants to directly notify the other end, which won’t work because it’s 
>the wrong thread for that. I was hoping that the streams would use normal Unix 
>I/O, since the comment about the TwoWayPipe class says "Typically backed by 
>socketpair() system call”.

So how do I set up streams to do I/O between threads?

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/EA5DCF15-8128-4F65-AE98-708AE1B75D1E%40mooseyard.com.


[capnproto] Xcode hits SIGUSR1 signal when I use an Executor

2022-08-30 Thread Jens Alfke
I have Cap’nProto RPC (in C++, on macOS) working well on the main thread, but I 
want to move it to a background thread for various reasons. However, my process 
is now raising SIGUSR1 signals, which the debugger breaks at, preventing the 
code from working.

I’m following the directions in the docs: in my background thread’s main 
function I call kj::setupAsyncIo(), then I call kj::getCurrentThreadExecutor() 
to get the Executor object. My main thread uses that Executor reference to pass 
lambdas that will run on the background thread and do the RPC stuff.

My immediate problem is that as soon as the main thread schedules a call with 
the Executor, LLDB (in Xcode) takes control, letting me know that the 
background thread has raised a SIGUSR1 signal. The backtrace is:

* thread #5, stop reason = signal SIGUSR1
  * frame #0: 0x0001ab672eb0 libsystem_kernel.dylib`poll + 8
frame #1: 0x000100bb0c78 `kj::UnixEventPort::PollContext::run(int) + 40
frame #2: 0x000100bb09ec  `kj::UnixEventPort::wait() + 352
frame #3: 0x000100ba4710  `kj::EventLoop::wait() + 40
frame #4: 0x000100ba4c90  
`kj::_::waitImpl(kj::Own&&, kj::_::ExceptionOrValue&, 
kj::WaitScope&) + 436
frame #5: 0x000100ba52fc  `kj::_::NeverDone::wait(kj::WaitScope&) const 
+ 76
…

 If I continue from this, the code seems to be deadlocked: nothing happens 
until I kill the process.

If I run without LLDB, the process gets past this point; the Executor seems to 
behave correctly and my lambda starts running on the background thread. 
However, working without a debugger is unacceptable; there’s no way I’m going 
to be able to troubleshoot the rest of my code without LLDB.

Is there a workaround to this? Like, a way to get LLDB to ignore the signal, or 
to get Cap’nP to use something other than a signal? I’m guessing I haven’t run 
into this before because I’ve only been using a single thread and for whatever 
reason Cap’nProto only uses this signal for inter-thread messaging … ?

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/16B01042-101B-4F3D-8E4F-D17C57DA4960%40mooseyard.com.


Re: [capnproto] Installtion Error for capnp on unix

2022-08-03 Thread Jens Alfke
(Also, if I may jump in with a pet peeve of mine: it’s better to post logs as 
text than as screenshots. Screenshots are not searchable, not accessible, don’t 
show more than a few dozen lines, and are of course much bigger. Attach the 
entire output as a text file, or at least just copy-and-paste the relevant 
text. I speak as someone who has had to try to diagnose way too many problems 
submitted as useless screenshots. Thanks.)

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/FF178E5D-D94C-4413-885D-009B730A4E72%40mooseyard.com.


Re: [capnproto] Warnings "EventLoop destroyed with events still in the queue. Memory leak?"

2022-06-07 Thread Jens Alfke


> On Jun 7, 2022, at 3:07 PM, Kenton Varda  wrote:
> 
> Info-level logs are generally meant to be enabled only for debugging, so the 
> idea here is you normally shouldn't see this log.

But I am debugging :) I’m debugging my code, using KJ logging. So I do see this 
somewhat scary-looking message mixed in with my own logs.

> All exceptions that are transmitted over RPC are info-logged 

So it's normal for this exception to be created & transmitted when a client 
connection closes? If so I’ll just ignore it from now on.

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/9B4D459A-AC88-40F9-86C6-37A2757DD63E%40mooseyard.com.


Re: [capnproto] Warnings "EventLoop destroyed with events still in the queue. Memory leak?"

2022-06-07 Thread Jens Alfke


> On Jun 7, 2022, at 9:53 AM, 'Kenton Varda' via Cap'n Proto 
>  wrote:
> 
> Ideally, you should set things up so that when the stack unwinds, all Promise 
> objects are destroyed before the EventLoop is destroyed. 

Thanks! I actually figured this out shortly after posting, but forgot to send a 
follow-up. I had to inspect some classes' member declarations carefully to find 
the two that were in the wrong order; swapping them fixed it.

But maybe you can help me with a less-annoying warning that I’m still getting. 
When either the client or the server connection closes, I always get an 
Info-level log:

returning failure over rpc; exception = capnp/rpc.c++:3107: failed: RpcSystem 
was destroyed.

It appears harmless, and no exception is actually thrown, but I’d rather not be 
logging this. Any idea what I might still be doing wrong?

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/23F7A5D0-8538-4C16-8E55-57FBC207BA70%40mooseyard.com.


[capnproto] Warnings "EventLoop destroyed with events still in the queue. Memory leak?"

2022-05-23 Thread Jens Alfke
I’m in the midst of improving the error handling in my code, but there’s a 
warning logged by KJ that I can’t figure out. I’d appreciate any advice or 
insight.

It happens when my client code fails to connect because server-side auth fails, 
so it gets an abrupt "Connection reset by peer” error that’s thrown from the 
first Promise::wait() call. That exception causes my client object to get 
destructed, and during its destructor the warning gets logged (with a bunch of 
backtrace.)

The message as logged from my onRecoverableException handler looks like:

expected head == nullptr [10bf07390 == nullptr]; EventLoop destroyed with 
events still in the queue.  Memory leak?; head->traceEvent() = 10152fc4c 
101548a28
kj::_::ImmediatePromiseNode 
>::get(kj::_::ExceptionOrValue&) (in myapp) + 0: returning here

The call stack is pretty long, so I’ve tried to clean it up a bit. “myapp” is 
app code. “snej::shs” is my implementation of the SecretHandshake secure-socket 
protocol, including CapnP glue code adapted from ez-rpc.c++.

myapp::KJExceptionCallback::onRecoverableException() at Logging.cc:80:28
kj::_::Debug::Fault::~Fault() + 172
kj::EventLoop::~EventLoop() + 432
kj::_::HeapDisposer::dispose() at 
memory.h:522:14
void kj::Disposer::dispose() const at 
memory.h:534:3
kj::Own::dispose() at memory.h:278:17
kj::Own::~Own() at memory.h:204:28
kj::Own::~Own() at memory.h:204:26
kj::AsyncIoContext::~AsyncIoContext() at async-io.h:876:8
kj::AsyncIoContext::~AsyncIoContext() at async-io.h:876:8
snej::shs::SecretRPCContext::~SecretRPCContext() at SecretRPC.cc:56:9
snej::shs::SecretRPCContext::~SecretRPCContext() at SecretRPC.cc:50:45
snej::shs::SecretRPCContext::~SecretRPCContext() at SecretRPC.cc:50:45
kj::Disposer::Dispose_::dispose() at 
memory.h:522:14
void kj::Disposer::dispose() const at 
memory.h:534:3
kj::Own::dispose() at memory.h:278:17
kj::Own::~Own() at memory.h:204:28
kj::Own::~Own() at memory.h:204:26
snej::shs::SecretRPCClient::Impl::~Impl() at SecretRPC.cc:283:29
snej::shs::SecretRPCClient::Impl::~Impl() at SecretRPC.cc:283:29
kj::_::HeapDisposer::disposeImpl() const at 
memory.h:433:60
kj::Disposer::Dispose_::dispose() at 
memory.h:528:14
void kj::Disposer::dispose() const at 
memory.h:534:3
kj::Own::dispose() at memory.h:278:17
kj::Own::~Own() at memory.h:204:28
kj::Own::~Own() at memory.h:204:26
snej::shs::SecretRPCClient::~SecretRPCClient() at SecretRPC.cc:383:59
snej::shs::SecretRPCClient::~SecretRPCClient() at SecretRPC.cc:383:57
kj::_::HeapDisposer::disposeImpl() const at 
memory.h:433:60
kj::Disposer::Dispose_::dispose() at 
memory.h:528:14
void kj::Disposer::dispose() const at memory.h:534:3
kj::Own::dispose() at memory.h:278:17
kj::Own::~Own() at memory.h:204:28
kj::Own::~Own() at memory.h:204:26
myapp::net::Client::ConnectionImpl::~ConnectionImpl() at Client.cc:281:19
myapp::net::Client::ConnectionImpl::~ConnectionImpl() at Client.cc:281:19
myapp::net::Client::ConnectionImpl::~ConnectionImpl() at Client.cc:281:19
std::__1::default_delete::operator() const at 
unique_ptr.h:57:5
std::__1::unique_ptr >::reset() at 
unique_ptr.h:318:7
std::__1::unique_ptr >::~unique_ptr() at 
unique_ptr.h:272:19
std::__1::unique_ptr >::~unique_ptr() at 
unique_ptr.h:272:17
myapp::net::Client::~Client() at Client.cc:314:21
myapp::net::Client::~Client() at Client.cc:314:21
myapp::SyncTask::_run() at SyncTask.cc:166:5
myapp::SyncTask::run() const at SyncTask.cc:82:9
kj::_::RunnableImpl kj::runCatchingExceptionshttps://groups.google.com/d/msgid/capnproto/59C02C00-95D1-4357-8F26-9E3F8A1C35DC%40mooseyard.com.


Re: [capnproto] Building with CMake

2022-05-14 Thread Jens Alfke

> On May 13, 2022, at 6:07 PM, Kenton Varda  wrote:
> 
> Do you mean that iOS was broken at the last release, but has been fixed at 
> master since then? (I don't know how to test iOS so I have no idea which 
> versions work or not…)

I just mean that AFAIK there are no binary libraries for iOS on your website. 
(Right?)

I did discover that I can run `cmake -G Xcode .` and CMake will generate an 
Xcode project file. Then I was able to change a few build settings in the 
project and get Xcode to build iOS static libs. I haven’t actually tested them 
yet, but this looks like a promising approach, even if it’s not as turn-key as 
just running CMake in my top-level project directory.

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/A18C5685-FBE1-4D85-A71E-40F4010BF426%40mooseyard.com.


[capnproto] Building with CMake

2022-05-13 Thread Jens Alfke
I want to build Cap’n Proto from source as part of my project; I know it’s 
preferred to download a release, but I need to support iOS and there are no 
releases for that AFAIK.

The build instructions at https://capnproto.org/install.html 
 seem out of date; they say to use 
autoconf, but the current sources have a CMakeFile and I found that the usual 
CMake build command work fine:
mkdir build_cmake && cd build_cmake
cmake ..
make

However, if I add capnproto as a subdirectory to my project’s CMakeLists.txt:
add_subdirectory(vendor/capnproto)
it doesn’t build. During the initial ‘cmake’ command for my project, I get 
several errors of the form:

CMake Error at vendor/capnproto/c++/cmake/CapnProtoMacros.cmake:106 
(add_custom_command):
  Error evaluating generator expression:

$

  No target "CapnProto::capnp_tool"
Call Stack (most recent call first):
  CMakeLists.txt:113 (capnp_generate_cpp)

I have no idea what this means, or what to do about it…

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/8FDA7AA9-F7A2-4FC7-BC86-DD3B569FF210%40mooseyard.com.


[capnproto] Build error on Raspbian, "undefined reference to `__atomic_load_8'"

2022-04-08 Thread Jens Alfke
I'm building CapnP 0.9.1 from source on a new Raspberry Pi 4 running Raspbian 
(because apt only has version 0.7.) 

curl -O https://capnproto.org/capnproto-c++-0.9.1.tar.gz
tar zxf capnproto-c++-0.9.1.tar.gz
cd capnproto-c++-0.9.1
./configure
make -j6 check
sudo make install

Everything went fine until the final "sudo make install" step:

...
libtool: link: g++ -I./src -I./src -DKJ_HEADER_WARNINGS -DCAPNP_HEADER_WARNINGS 
-DCAPNP_INCLUDE_DIR=\"/usr/local/include\" -pthread -O2 -DNDEBUG -pthread 
-DKJ_HAS_ZLIB -pthread -o .libs/capnp src/capnp/compiler/module-loader.o 
src/capnp/compiler/capnp.o  ./.libs/libcapnpc.so ./.libs/libcapnp-json.so 
./.libs/libcapnp.so ./.libs/libkj.so -lpthread -pthread
/usr/bin/ld: ./.libs/libcapnp.so: undefined reference to `__atomic_load_8'
/usr/bin/ld: ./.libs/libcapnp.so: undefined reference to `__atomic_store_8’

I’m guessing the missing symbols are CPU intrinsics for 64-bit atomic 
operations. Could this have something to do with the fact that Raspbian is 
still running in 32-bit on a 64-bit CPU?

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/D31A68E1-75DA-404E-99D4-74A02525A562%40mooseyard.com.


[capnproto] Having trouble with Github CI

2022-02-26 Thread Jens Alfke
I’m trying to get my (C++) project to build in Github Actions, but getting 
compile errors because apparently there’s a version mismatch between the Cap’n 
Proto headers and tool.

I don’t build Cap’n Proto as part of the project; instead I use a package 
manager to install it. My CMakeLists.txt has a step to compile my interface:
find_package(CapnProto CONFIG REQUIRED)
capnp_generate_cpp(myCapnPSources myCapnPHeaders src/interface.capnp)

This works fine in local builds, both macOS and Ubuntu.

In my Github Actions yaml file, I added a build step that uses the get-package 
action:
  - name: Install Capn Proto
uses: mstksg/get-package@v1
with:
  brew: capnp
  apt-get: capnproto libcapnp-dev

Unfortunately the C++ compile then fails with the error: "Version mismatch 
between generated code and library headers.  You must use the same version of 
the Cap'n Proto compiler and library.”

I assume this means that on the Github runner the `capnp` tool is from a 
different version than the headers. I don’t know why that would be, when I had 
apt install both packages. (And why would there be a second installation of 
Cap’n Proto at all?)

Has anyone successfully gotten Github Actions to build C++ based Cap’n Proto 
projects?

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/A1E39982-9835-4E45-B9E1-397CC5B286FF%40mooseyard.com.


[capnproto] Writing tests for RPC-based code?

2022-02-21 Thread Jens Alfke
Does anyone have advice on writing C++ automated tests for RPC-based code? 
(FWIW, I use the Catch2 unit-test framework, but I don’t restrict it to true 
‘unit’ tests.) Say I’ve got an interface file, a class `Client` built atop 
classes generated from that interface, and a class `Server` that accepts TCP 
connections from a `Client`. I want to write a test that creates a Client and 
Server, connects them to each other, and then invokes some operations on the 
Client and asserts the correct results.

The first step of course is creating a connection. It looks like the simplest 
supported mechanism is to open a POSIX pipe and then create kj AsyncStreams on 
its two file descriptors. That means I’ll need an alternative Client 
constructor that takes a file descriptor or stream instead of a hostname/port…

I’d love to take a look at anyone’s test code that does stuff like this.

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/CED5FAAE-EC6B-47E7-BDE3-58F3C1DD001F%40mooseyard.com.


Re: [capnproto] Implementing SecretHandshake secure-connection support in C++

2022-01-13 Thread Jens Alfke



> On Jan 13, 2022, at 9:31 AM, Kenton Varda  wrote:
> 
> It looks like the chacha20 functions have variants with an "ic" parameter, 
> which lets you specify the block counter, but the salsa20 functions don't 
> have this for some reason.

A block counter would still require dividing the stream into blocks. 
Fixed-size blocks won’t work because the codec will stall until a block is 
completed, which would deadlock most interactive protocols. 
Variable-size blocks depend on the byte counts passed to the writer, which then 
means writing the block size into the output, and assembling a block on the 
read side. This turns out to be just as much work as using the higher level 
APIs like crypto_secretstream_xchacha20poly1305, or for that matter 
crypto_secretbox, both of which authenticate; so might as well just use them. 
(As does Scuttlebutt.)

Bizarrely, there appears to be no actual streaming API where your data gets 
encrypted with successive portions of the infinite cipher stream. This is 
further confirmation of my belief that cryptographers should never be allowed 
to design APIs.

So. Current plan is to write a stream wrapper around crypto_secretbox. This 
involves annoying stuff like buffering data, but it’s not rocket science.

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/D78A20B1-66F3-4D20-9313-2A2F1D65967E%40mooseyard.com.


Re: [capnproto] Implementing SecretHandshake secure-connection support in C++

2022-01-12 Thread Jens Alfke

>> Hmm if you're using a plain xsalsa20 stream and not secret boxes, does that 
>> mean you're implementing only encryption, not authentication? Note that 
>> XSalsa20 and related ciphers work by generating a random stream, and then 
>> XORing it with the plaintext.

FYI: It turns out that my stream-encryption code is totally broken anyway. I 
naively believed that Sodium’s `crypto_stream_xor` implemented a stream cipher, 
as the name implies — but it doesn’t. The key and nonce parameters are both 
const, so it’s stateless, and just xor’s the buffer with the same bit-stream 
every time it’s called.

I am not a cryptographer, but I find this baffling and pointless. Why call this 
a “stream cipher” when the API only allows you to encrypt a single 
(variable-size) block of data?

Looks like I’m forced to implement a chunk-based protocol after all. Good news 
is it’ll be tamper-proof.

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/FD4A7BDA-5DF1-4F4B-B574-57EFB4DE72FB%40mooseyard.com.


[capnproto] Noob question: Can an interface method return null?

2022-01-12 Thread Jens Alfke
This seems like a dumb question, but I’ve been unable to find an answer. Does 
the RPC system support null values? In particular, if an RPC method returns an 
interface, is it able to return null?

Say Widget is an interface, and in another interface I’ve got a method
widgetNamed @1 (name: String) -> (widget: Widget);
Can this method return null? I’m beginning to suspect it can’t, because when it 
tries to I get an error "Pipeline call on a request that returned no 
capabilities or was already closed”. (The implementation is in C++; to return 
null it just abstains from calling context.getResults().setWidget().)

If it can’t, what is the idiomatic way to provide an optional return value? Do 
I return an exception, or do I create my own `Optional` type as a union?

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/5862EBA9-F772-44A4-9736-72F70AAB0B86%40mooseyard.com.


Re: [capnproto] Implementing SecretHandshake secure-connection support in C++

2022-01-12 Thread Jens Alfke



> On Jan 12, 2022, at 9:22 AM, Kenton Varda  wrote:
> 
> Sorry for the long delay in replying, I had a baby the day you sent this!

Congratulations!  I remember those days...

> This is neat! How many round trips are needed to set up a connection?

There are four messages: C->S, S->C, C->S, S->C. In the current implementation 
they happen one at a time, so I guess that’s two round trips? But it looks as 
though messages 1 & 2 can be sent concurrently, and also 3 & 4.

I dimly recall that there are some additional TCP hacks one can do, to 
piggyback a small payload on the initial packets that open the connection, but 
I don’t feel like cracking open TCP/IP Illustrated right now :-p

> Hmm if you're using a plain xsalsa20 stream and not secret boxes, does that 
> mean you're implementing only encryption, not authentication? Note that 
> XSalsa20 and related ciphers work by generating a random stream, and then 
> XORing it with the plaintext. So although the attacker can't decrypt the 
> bytes, they can flip individual bits in the ciphertext and this will result 
> in the same bit being flipped in the plaintext.

Yeah, there are no integrity checks in the data stream, and I agree that’s a 
weakness*. Adding MACs requires adding a block- or message-oriented layer on 
top, like SecretBox, the way that Scuttlebutt does. This feels like redundant 
effort since Cap’nP also is itself message-oriented; my guess is that there’s a 
higher level API inside Cap’nP that exposes the message framing, and the MAC 
could be added there, but I have not yet delved deeper into the way Cap’nP 
works. (Hints welcome.)

(Or if there’s a clever stream-based way to insert MACs without having to build 
a framing layer, that would be even better. I’ve read my share of crypto 
textbooks, maybe I’ve just forgotten that bit.)

—Jens

* I should probably call this out in the readme, shouldn’t I.

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/D78A1434-B928-43D4-951D-5CFA2E021B8E%40mooseyard.com.


[capnproto] How can a server method get info about the client connection?

2021-12-16 Thread Jens Alfke
Now that I've implemented authenticated connections, *I need my server-side 
methods to be able to find out the identity (public key) of the connected 
peer*. So for example, my method LibraryImpl::checkoutBook(isbn) needs to 
check the identity of the client (as given in the SecretHandshake when 
connecting) to determine if they have permission to get that book.

(A different example that doesn't involve SecretHandshake is one where a 
server-side method wants to look at the IP address of the client. Or, if 
using TLS, the client's TLS cert.)

What's the best way to do this? I'm using my modified version of 
EzRpcServer, and I'm getting familiar with its innards but I can't claim to 
really understand this stuff yet. It appears that the "mainInterface" 
capability vended by the server is a singleton, shared by all clients, so I 
can't stuff per-client info into it. The point of vending is the restore() 
method, but that method can't tell what client it's being called on behalf 
of...

--Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/b89502d7-8450-4f97-8c3a-ffdb9a4b4663n%40googlegroups.com.


Re: [capnproto] Implementing SecretHandshake secure-connection support in C++

2021-12-14 Thread Jens Alfke
After some more work and cleanup, I’ve published my source code at
https://github.com/snej/secret-handshake-capnp 


Suggestions and fixes gratefully accepted, especially since much of the code is 
taken from Cap’n Proto itself and was “adapted for radio by putting it on a 
board and banging a few nails through it”, as Monty Python put it.

Here’s the gist of the README:

SecretHandshake For Cap’n Proto

C++ implementation of the SecretHandshake 
 protocol for the 
awesome Cap’n Proto  RPC library. This lets you upgrade 
your network connections with encryption and mutual authentication, without all 
the overhead of OpenSSL.

(You don’t actually need Cap’n Proto to use this, but if so you’ll need to 
provide your own networking code.)

 About 
SecretHandshake

SecretHandshake is “a mutually authenticating key agreement handshake, with 
forward secure identity metadata.” It was designed by Dominic Tarr and is used 
in the Secure Scuttlebutt P2P social network.

It’s based on 256-bit elliptic Ed25519 key-pairs. The peers each maintain a 
long-term key pair, whose public key serves as a global identifier. The peer 
making the connection (“client”) must know the public key of the other peer 
(“server”) to be able to connect, and the server learns the client’s public key 
during the handshake. Each peer receives proof that the other has the matching 
private key. Much more detail is available in the design paper 
.

The handshake also produces two session keys, which are then used to encrypt 
the channel with the 256-bit symmetric XSalsa20 cipher. (This is not strictly 
speaking part of the SecretHandshake protocol, which ends after key agreement. 
Scuttlebutt uses a different encryption scheme based on libSodium’s “secret 
box”.)

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/8C607A75-64AC-4E6D-A80D-5C0877B7656F%40mooseyard.com.


Re: [capnproto] Implementing SecretHandshake secure-connection support in C++

2021-12-11 Thread Jens Alfke
I just got it working! Once I got the code finished and compiling, there were 
just a few runtime issues before it succeeded.

The protocol  is 
pretty simple — each side sends a challenge, receives the other’s challenge, 
then sends a response; the result is two shared symmetric keys for a stream 
cipher. So it wasn’t hard to splice into an AsyncStream.

I hacked at the TLS code and EzRpc. The result isn’t pretty and could probably 
have been done in half the code if I knew what I was doing, but at least it 
works. I’ll try to factor it out and publish it as a Git repo, then perhaps 
experts can suggest how to clean it up.

—Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/16416FA5-CBA5-4FCE-A46A-72182AFC32C7%40mooseyard.com.


[capnproto] Implementing SecretHandshake secure-connection support in C++

2021-12-09 Thread Jens Alfke
I'm starting to implement support for SecretHandshake 
, a "secure-channel 
based on a a mutually authenticating key agreement handshake, with forward 
secure identity metadata". shs1-c  
implements 
the crypto part, resulting in a pair of symmetric stream-cipher keys; 
beyond that I'm going to copy and paste and hack the C++ Cap'n Proto TLS 
code 
,
 
despite being a total newbie at kj.

Basically all I need to do is create a Cap'n Proto RPC connection that 
splices into the TCP I/O and initially does a couple of data exchanges via 
shs1-c, then filters the data streams through the ciphers.

I'm writing in case anyone has knowledge about the kj side of this that 
they'd like to share.

I'll reply here once I've got this working, and I plan to release the code 
as open source.

--Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/fe6b6564-3f08-478e-af5c-2bf461ea0e81n%40googlegroups.com.


Re: [capnproto] Unsubscribe in pub/sub model

2021-12-02 Thread Jens Alfke
I'm also implementing pub-sub, so I was glad to see this thread before I 
wasted too much time. I'm implementing this pattern, but having trouble on 
the client side.

In terms of the example interface, I've created my SubscriberImpl class, 
and written the code to send the "subscribe" message. Now I want to store 
the returned Subscription capability reference in my SubscriberImpl, so it 
can own it and drop it when it's done.

However, I can't figure out how to keep a reference to the SubscriberImpl, 
since I have to move it to the Request object (calling setSubscriber) and 
afterwards it's gone, so I can't call it again.

auto rq = remotePublisher.subscribeRequest();
auto impl = kj::heap();
rq.setSubscriber(std::move(impl));
auto promise = rq.send().then([&](auto response) {return 
response.getSubscription();});
// *somehow convey the promise to the SubscriberImpl...?*

I'm sure this is just due to my incomplete understanding of how 
Promise/Client/Server objects work...
Thanks,

--Jens

On Monday, November 22, 2021 at 8:53:42 AM UTC-8 ken...@cloudflare.com 
wrote:

> Hi Mitsuo,
>
> I recommend designing the interface like this:
>
> interface EventPublisher{
> interface Subscriber {
> updateEvent @0 (event: Int32) -> ();
> }
>
> interface Subscription {}
> subscribe @0 (subscriber: Subscriber) -> (result: Int32, subscription: 
> Subscription);
> # To unsubscribe, drop the returned `subscription`.
> }
>
>
> Here, subscribe() returns a `subscription` object. This object has no 
> methods. But, when the capability is dropped, then the destructor will run 
> on the server side. Atn that point, you can remove the subscription.
>
> A big advantage of this approach is that it handles connection failures 
> gracefully. If the client randomly disconnects, the `subscription` 
> capability is automatically dropped, thus unsubscribing the client. This 
> way you don't end up stuck sending messages to a disconnected subscriber.
>
> It also solves your problem because you can remember arbitrary metadata 
> about the subscriber within the `Subscription` object, so you know what to 
> remove when it's destroyed.
>
> -Kenton
>
> On Mon, Nov 22, 2021 at 12:40 AM mitsuo  
> wrote:
>
>> Hi,
>>
>> I'm trying to implement pub/sub like communication model with the 
>> following scheme.
>> *pubsub.capnp*
>> *interface EventPublisher{*
>> *interface Subscriber {*
>> *updateEvent @0 (event: Int32) -> ();*
>> *}*
>> *subscribe @0 (subscriber: Subscriber) -> (result: Int32);*
>> *unsubscribe @1 (subscriber: Subscriber) -> (result: Int32);*
>> *}*
>>
>> I'm using *kj::Vector m_subscribers *to 
>> store the current subscribers.
>> When I try to implement unsubscribe and remove the Subscriber from the 
>> Vector, I couldn't find good method to do that.
>> Could you give me some advice?
>>
>> *server implementation*
>> *class EventPublisherImpl final : public EventPublisher::Server {*
>> * protected:*
>> *  ::kj::Promise subscribe(SubscribeContext context) {*
>> *cout << "subscribe request received" << endl;*
>> *m_subscribers.add(context.getParams().getSubscriber());*
>> *return kj::READY_NOW;*
>> *  }*
>>
>> *  ::kj::Promise unsubscribe(UnsubscribeContext context) {*
>> *cout << "unsubscribe request received" << endl;*
>> *auto unsub = context.getParams().getSubscriber();*
>>
>> *// I want to remove usub from subscribers like 
>> m_subscribers[unsub].erase();*
>> *// But I couldn't find a method to compare*
>> *// "EventPublisher::Subscriber::Client" such as == operator or 
>> public method*
>> *// to distinguish the client.*
>> *//*
>> *// One solution is having an additional argument(id) for this 
>> purpose but*
>> *// that requres additional management of ID.*
>> *//  subscribe @0 (subscriber: Subscriber, id: Int32) -> (result: 
>> Int32);*
>> *//  unsubscribe @1 (id: Int32) -> (result: Int32);*
>>
>> *// what I can do is erase everything but this is not my goal*
>> *m_subscribers.clear();*
>> *return kj::READY_NOW;*
>> *  }*
>>
>> * private:*
>> *  kj::Vector m_subscribers;*
>> *};*
>> Thank you,
>>
>> -- 
>> 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 capnproto+...@googlegroups.com.
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/capnproto/26c4964f-21a2-4fe2-a410-7673786d40c9n%40googlegroups.com
>>  
>> 
>> .
>>
>

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view 

[capnproto] Can't put C++ Client object in std::map

2021-12-01 Thread Jens Alfke
Hi! I'm getting started with capnp, using C++ bindings (with C++17 compiled 
by Clang 12.) I'm having trouble storing remote object references, i.e. 
xx::Client objects, in STL collections. For example:

std::map foobars;
...
Foobar::Client c = promise.wait(waitScope).getFoobar();
foobars.insert({name, c});// Compile error

The error is "*the parameter for this explicitly-defaulted copy constructor 
is const, but a member or base requires it to be non-const*."

I eventually worked out that the error is because *Client's copy 
constructor takes a `Client&` parameter, i.e. requires a mutable reference, 
which breaks the std::pair class* because it needs to be able to copy a 
const reference. And if you can't put a client into a std::pair, you can't 
put it into a std::map or std::unordered_map.

I assume there must be a reason for leaving out the standard `const` in the 
copy constructor's parameter; but I can't work out what it would be. I know 
Client objects are wrappers for a pointer to a ref-counted value, so 
copy-constructing one bumps the value's ref-count, but that value is a 
separate object so it shouldn't matter whether the Client reference is 
const or not. (FYI, I've implemented my own ref-counted objects in C++ so 
I'm pretty familiar with the details...)

Is there a good workaround for storing RPC client objects in STL maps? 
Thanks!

--Jens

-- 
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 capnproto+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/63af6853-ac43-4c75-a161-a4c939199e93n%40googlegroups.com.