Add receive-and-decode-msg to decode multipart messages.

Julien LepillerSat Oct 10 23:56:57+0200 2020

554a2c6

Add receive-and-decode-msg to decode multipart messages.

doc/guile-netlink.texi

266266
@code{deserialize} (@xref{Data Types})
267267
@end deffn
268268
269+
@deffn {Scheme Procedure} receive-and-decode-msg @var{sock} @var{decoder} @
270+
    [#:@var{addr}]
271+
Receives one or more messages from @var{sock} from @var{addr}.  this procedure
272+
is blocking.  If not passed, @var{addr} defaults to the address of the kernel.
273+
This procedure returns a list of messages that were decoded using @var{decoder}.
274+
275+
When the answer has the @code{NLM_F_MULTI} flag, this procedure decodes the next
276+
message, until it receives a @code{NLMSG_DONE} message.  It returns the list
277+
of every netlink messages it received, including the @code{NLMSG_DONE}.
278+
@end deffn
279+
269280
@node Netlink API
270281
@section Netlink API
271282

netlink/connection.scm

2727
            close-socket
2828
            send-msg
2929
            receive-msg
30+
            receive-and-decode-msg
3031
            get-addr))
3132
3233
(define libc (dynamic-link))

117118
    (when (> size 0)
118119
      (bytevector-copy! bv 0 answer 0 size))
119120
    answer))
121+
122+
(define* (receive-and-decode-msg sock decoder
123+
                                 #:key (addr (get-addr AF_NETLINK 0 0)))
124+
  (let* ((answer (receive-msg sock #:addr addr))
125+
         (size (bytevector-length answer)))
126+
    (let loop ((messages '()) (pos 0))
127+
      (if (>= pos size)
128+
          (let ((last-message (car messages)))
129+
            (if (and
130+
                  (equal? (logand (message-flags last-message) NLM_F_MULTI)
131+
                          NLM_F_MULTI)
132+
                  (> (message-kind last-message) NLMSG_OVERUN))
133+
                (append (reverse messages)
134+
                        (receive-and-decode-msg sock decoder #:addr addr))
135+
                (reverse messages)))
136+
          (let ((message (deserialize 'message decoder answer pos)))
137+
            (loop (cons message messages)
138+
                  (+ (data-size message) pos)))))))