strongswan / davici

Decoupled Asynchronous VICI
GNU Lesser General Public License v2.1
20 stars 18 forks source link

davici_queue_streamed - unit test example generates VICI errors in strongswan.log #6

Closed PhilT-00 closed 3 years ago

PhilT-00 commented 3 years ago

I am working on a davici based application that implements a "list-sas" command using the process structure found in the unit test stream.c:

  1. davici_connect_unix
  2. davici_new_cmd
  3. davici_queue_streamed
  4. runio
  5. davici_disconnect

When invoked, I am seeing VICI errors in strongswan.log when there are no security associations:

Strongswan 5.6.2 davici 1.3 + Davici GitHub isprint() patch

On tracing this streamed process, davici_queue_streamed creates three requests DAVICI_CMD_REQUEST, DAVICI_EVENT_REGISTER, DAVICI_EVENT_UNREGISTER but runio processing fails to remove DAVICI_EVENT_UNREGISTER before closing the connection - davici encounters a DAVICI_END condition that closes the connection before StrongSwan can send the last part of the message.

It feels like the example code is a cutdown version of the process that works for testing but fails when used as a template in real code because the DAVICI_END condition is prematurely generated before the entire response message has been received.

Are there any other code examples that implement davici_queue_streamed in a way that can be scaled for production code?

My best guess (so far) at the cause is that the request should include SECTION_START and SECTION END so that the connection is not closed early, and that the errors are indicative of StrongSwan being unable to send the final part of the message.

PhilT-00 commented 3 years ago

The problem was in the application (which is a good thing) and not in the davici interface, found by long debug trace session. The comment that davic_queue_streamed calls the event_cb twice with response == NULL had been overlooked. The problem is resolved, and strongswan vici header errors no longer appear in syslog.

It would be good to

The event_cb code now looks like the following snippet

event_cb( conn, errcode, res, user )
{
  if (res)
    processEvent( res, user )
  else
  {
      auto myData = (MyData*) user;
      if (myData->registered)
          myData->complete = true;   // last event has been received
      else
          myData->registered = true;  // ready to receive first event
   }
}