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.