On Monday, November 6, 2017 at 12:14:18 PM UTC-8, Russell Haley wrote:
>
>
>
> On Monday, November 6, 2017 at 11:49:43 AM UTC-8, Ben Noordhuis wrote:
>>
>> On Mon, Nov 6, 2017 at 7:56 PM, Russell Haley <[email protected]> 
>> wrote: 
>> > Hello, 
>> > 
>> > I'm new to C patterns and I am experimenting with libuv to write a 
>> > simulator. The idea is to create a context struct to be passed around 
>> as a 
>> > pointer/handle to various timed and event based callback functions. I 
>> would 
>> > like this simulator to have a "heartbeat" that sends UDP every x 
>> period, as 
>> > well as respond to UDP messages received on a different port. I would 
>> like 
>> > the system to decides at runtime if there are flags in the context that 
>> > block it from sending (i.e. handle->send=0;). 
>> > 
>> > For bonus points, I would like to be able to start a TCP based module 
>> if I 
>> > receive a certain message on the UDP receive port and then stop it once 
>> the 
>> > routine completes. I am hoping I can just drop a routine on the default 
>> loop 
>> > (from within my uv_udp_recv_cb) for processing until completion which 
>> would 
>> > be signaled in a TCP callback (haven't delved into the TCP stuff 
>> yet...). 
>> > 
>> > After about 1 hour of searching I haven't found any examples of what I 
>> am 
>> > trying to do. Most of the example patterns are very simplistic. This 
>> dearth 
>> > of information leads me to one of two conclusions: 1) I am trying to do 
>> > something the wrong way or 2) nobody in the entirety of using libuv has 
>> ever 
>> > ever ever tried to do what I am attempting now. I assume the problem is 
>> the 
>> > former. ;) 
>> > 
>> > What I have so far: 
>> > 
>> > - An example udp listener from the docs. It listens faithfully on the 
>> port I 
>> > assign. 
>> > - A udp client, again from the docs. My first kick simply sends a 
>> message 
>> > and then exists . My next planned attempt was to use a timer to send 
>> the 
>> > information repeatedly. I have realized that the timer callback needs 
>> to 
>> > have my context handle, which prompted this question. I will finish my 
>> > example code and then post it here while awaiting a possible answer. 
>> > 
>> > Please let me know if I can provide some more background (context? tee 
>> hee). 
>> > 
>> > Regards, 
>> > 
>> > Russ 
>>
>> It's not entirely clear to me what you want to accomplish but if you 
>> want to attach state/context to a handle or request, you can use the 
>> handle->data and req->data fields. or embed them in another struct and 
>> use container_of() to look up the embedder.  You can find a 
>> container_of() definition in the libuv sources. 
>>
>
> Thanks so much for responding. I just stumbled over your answer in uv.h 
> (described in UV_HANDLE_FIELDS) and then found it in the documentation. I 
> missed the context section at the bottom of the basics page.  :(
>
> Thanks for the answer and sorry for the noise! 
>
> Russ
>

Okay, a little more noise. I'm getting a segmentation fault in libuv.so.1 
that I can't seem to debug (unsurprising with my limited gdb skills). The 
following code is my udp client. It's supposed to:
1) Set up the context in main()
2) Start a timer to tick once, then once per second. 
3) On each tick, send a udp message and augment the counter.
4) If the counter is 10, stop.

udp-spammer.c:

#include <unistd.h>
#include <stdio.h>
#include <uv.h>
#include <stdlib.h>
#include <string.h>

#define UDP_SEND_PORT           49284
#define UDP_REC_PORT            49280

#define VMDS_ADDR "127.0.0.1"
#define TRU_ADDR "127.0.0.1"
#define ON 1
#define OFF 0

typedef struct context_t {
    uv_udp_t* send_ctx;
    int count;
    int send;
    uv_buf_t* message;
}context_t;


static void s_alloc_cb(uv_handle_t* handle, size_t suggested_size, 
uv_buf_t* buf) {
  buf->base = malloc(suggested_size);
  buf->len = suggested_size;
}

void on_send (uv_udp_send_t* req, int status)
{
    printf("Status: %d\n",status);
}

uv_buf_t make_sd_msg(char* msg)
{
    uv_buf_t buf = uv_buf_init(msg, strlen(msg));
    return buf;
}

void spam(uv_timer_t* h)
{
    context_t* ctx = (context_t*)h->data;
    if(ctx == NULL)
    {
        printf("Esplode!");
        exit(1);
    }

    struct sockaddr_in broadcast_addr;
    uv_ip4_addr(VMDS_ADDR, 0, &broadcast_addr);
    uv_udp_bind(ctx->send_ctx, (const struct sockaddr *)&broadcast_addr, 0);

    uv_udp_send_t send_req;

    struct sockaddr_in remote_addr;
    uv_ip4_addr(TRU_ADDR, UDP_REC_PORT, &remote_addr);
    uv_udp_send(&send_req, ctx->send_ctx, ctx->message, 1, (const struct 
sockaddr *)&remote_addr, on_send);

    ctx->count++;
    if(ctx->count >= 10)
    {
        uv_timer_stop(h);
    }
}

int main() {

    uv_loop_t *loop;
    uv_timer_t timed;
    context_t ctx;

    loop = uv_default_loop();

    ctx.send = 1;
    ctx.count = 0;
    uv_buf_t msg =  make_sd_msg("Hello Lucy!\n\0");
    ctx.message = &msg;
    uv_udp_t snd;
    uv_udp_init(loop, &snd);
    ctx.send_ctx = &snd;

    timed.data = &ctx;

    uv_timer_init(loop, &timed);
    uv_timer_start(&timed, spam, 0,1000);

    return uv_run(loop, UV_RUN_DEFAULT);
}



So far, it sends the first UDP message and then I get a SIGSEV in 
libuv.so.1. bt isn't telling me much that I can use:

0xb7fad4bd in ?? () from /usr/lib/i386-linux-gnu/libuv.so.1
(gdb) bt
#0  0xb7fad4bd in ?? () from /usr/lib/i386-linux-gnu/libuv.so.1
#1  0xb7fad852 in ?? () from /usr/lib/i386-linux-gnu/libuv.so.1
#2  0xb7fa0be9 in uv_run () from /usr/lib/i386-linux-gnu/libuv.so.1
#3  0x08048ad4 in main () at udp-spammer.c:86

Any help would be grand. 

Thanks!
Russ

-- 
You received this message because you are subscribed to the Google Groups 
"libuv" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/libuv.
For more options, visit https://groups.google.com/d/optout.

Reply via email to