chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Chicken-users] Updating the zmq egg


From: Thomas Chust
Subject: Re: [Chicken-users] Updating the zmq egg
Date: Fri, 06 Mar 2015 12:44:09 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.5.0

On 2015-03-06 02:00, Matt Gushee wrote:
> [...]
> Another issue with message length is whether there should be a default
> value. There is a Scheme function that generates a buffer for both
> sending and receiving functions.
> [...]

Hello,

for sending, I wouldn't allocate a separate buffer but just pass a
pointer to the contents of a string or blob and the length of the
container to the C function.

For receiving, however, there is no way to know how large the buffer
must be without also knowing the application level protocol. Since
CHICKEN is a high level language, I would try to avoid choosing an
arbitrary buffer size or even forcing the programmer to specify some
specific buffer size, since this could lead to memory overflow errors.

I would recommend to use the zmq_msg_init and zmq_msg_recv functions to
receive a message of arbitrary length and leave the allocation problems
to 0MQ, then you can extract the actual data and its length from the
message object using zmq_msg_data and zmq_msg_size. This approach is
somewhat less efficient than receiving into a prepared buffer, but it is
much easier to implement correctly.

For efficiency, you could provide an alternative API where the
programmer passes in a buffer and optional length that would receive the
message, but that API should definitely perform bounds checking.

Everything could be wrapped into a binding like this (beware, this code
snippet is completely untested):

(define (zmq-recv sock #!optional buf ofs len)
  (if buf
      (let* ((ofs (or ofs 0))
             (len
              (cond
               ((string? buf)
                (let ((len (or len (- (string-length buf) ofs))))
                  (assert (and (<= 0 ofs)
                               (< (+ ofs len) (string-length buf))))
                  len))
               ((blob? buf)
                (let ((len (or len (- (blob-size buf) ofs))))
                  (assert (and (<= 0 ofs)
                               (< (+ ofs len) (blob-size buf))))
                  len))
               (else
                (error 'zmq-recv "unknown buffer type")))))
        (if (negative?
             ((foreign-lambda* int ((c-pointer sock)
                                    (scheme-pointer buf)
                                    (size_t ofs) (size_t len)
                                    (int flags))
                "C_return(zmq_recv("
                "  sock, ((char *)buf) + (ptrdiff_t)ofs, len"
                "));")
              sock buf ofs len 0))
            (error 'zmq-recv "receive failed")
            buf))
      (let ((msg
             (make-blob (foreign-value "sizeof(zmq_msg_t)" size_t))))
        (if (negative?
             ((foreign-lambda int "zmq_msg_init" scheme-pointer) msg))
            (error 'zmq-recv "failed to initialize message")
            (set-finalizer!
             msg (foreign-lambda int "zmq_msg_close" scheme-pointer)))
        (if (negative?
             ((foreign-lambda int "zmq_msg_recv"
               scheme-pointer scheme-pointer int)
              msg socket 0))
            (error 'zmq-recv "receive failed")
            (let* ((len
                    ((foreign-lambda size_t "zmq_msg_size"
                      scheme-object)
                     msg))
                   (buf (make-blob len)))
              (move-memory!
               ((foreign-lambda c-pointer "zmq_msg_data" scheme-object)
                msg)
               buf len)
              buf)))))

I hope this helps :-)

Ciao,
Thomas


-- 
When C++ is your hammer, every problem looks like your thumb.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]