diff --git a/mio/lib/dns.c b/mio/lib/dns.c index d85d639..ff4a742 100644 --- a/mio/lib/dns.c +++ b/mio/lib/dns.c @@ -99,12 +99,13 @@ static mio_oow_t dn_length (mio_uint8_t* ptr, mio_oow_t len) struct mio_dnss_t { - mio_t* mio; + MIO_SVC_HEADERS; }; struct mio_dnsc_t { - mio_t* mio; + MIO_SVC_HEADERS; + mio_dev_sck_t* sck; mio_sckaddr_t serveraddr; mio_oow_t seq; @@ -158,7 +159,6 @@ static void dns_on_disconnect (mio_dev_sck_t* dev) { } - mio_dnsc_t* mio_dnsc_start (mio_t* mio) { mio_dnsc_t* dnsc = MIO_NULL; @@ -168,6 +168,7 @@ mio_dnsc_t* mio_dnsc_start (mio_t* mio) if (!dnsc) goto oops; dnsc->mio = mio; + dnsc->stop = mio_dnsc_stop; MIO_MEMSET (&minfo, 0, MIO_SIZEOF(minfo)); minfo.type = MIO_DEV_SCK_UDP4; /* or UDP6 depending on the binding address */ @@ -185,12 +186,14 @@ mio_uint32_t ia = 0x01010101; /* 1.1.1.1 */ mio_sckaddr_initforip4 (&dnsc->serveraddr, 53, (mio_ip4addr_t*)&ia); } + MIO_SVC_REGISTER (mio, (mio_svc_t*)dnsc); return dnsc; oops: if (dnsc) { if (dnsc->sck) mio_dev_sck_kill (dnsc->sck); + mio_freemem (mio, dnsc); } return MIO_NULL; } @@ -198,6 +201,8 @@ oops: void mio_dnsc_stop (mio_dnsc_t* dnsc) { mio_t* mio = dnsc->mio; + if (dnsc->sck) mio_dev_sck_kill (dnsc->sck); + MIO_SVC_UNREGISTER (mio, dnsc); mio_freemem (mio, dnsc); } diff --git a/mio/lib/main.c b/mio/lib/main.c index ddcd368..9c9979f 100644 --- a/mio/lib/main.c +++ b/mio/lib/main.c @@ -658,7 +658,7 @@ int main (int argc, char* argv[]) sin.sin_family = AF_INET; sin.sin_port = htons(1234); */ /* - udp = (mio_dev_udp_t*)mio_makedev(mio, MIO_SIZEOF(*udp), &udp_mth, &udp_evcb, &sin); + udp = (mio_dev_udp_t*)mio_dev_make(mio, MIO_SIZEOF(*udp), &udp_mth, &udp_evcb, &sin); if (!udp) { printf ("Cannot make udp\n"); diff --git a/mio/lib/mio-pro.c b/mio/lib/mio-pro.c index ad1b452..ff2190f 100644 --- a/mio/lib/mio-pro.c +++ b/mio/lib/mio-pro.c @@ -758,17 +758,17 @@ static mio_dev_pro_slave_t* make_slave (mio_t* mio, slave_info_t* si) switch (si->id) { case MIO_DEV_PRO_IN: - return (mio_dev_pro_slave_t*)mio_makedev( + return (mio_dev_pro_slave_t*)mio_dev_make( mio, MIO_SIZEOF(mio_dev_pro_t), &dev_pro_methods_slave, &dev_pro_event_callbacks_slave_in, si); case MIO_DEV_PRO_OUT: - return (mio_dev_pro_slave_t*)mio_makedev( + return (mio_dev_pro_slave_t*)mio_dev_make( mio, MIO_SIZEOF(mio_dev_pro_t), &dev_pro_methods_slave, &dev_pro_event_callbacks_slave_out, si); case MIO_DEV_PRO_ERR: - return (mio_dev_pro_slave_t*)mio_makedev( + return (mio_dev_pro_slave_t*)mio_dev_make( mio, MIO_SIZEOF(mio_dev_pro_t), &dev_pro_methods_slave, &dev_pro_event_callbacks_slave_err, si); @@ -780,7 +780,7 @@ static mio_dev_pro_slave_t* make_slave (mio_t* mio, slave_info_t* si) mio_dev_pro_t* mio_dev_pro_make (mio_t* mio, mio_oow_t xtnsize, const mio_dev_pro_make_t* info) { - return (mio_dev_pro_t*)mio_makedev( + return (mio_dev_pro_t*)mio_dev_make( mio, MIO_SIZEOF(mio_dev_pro_t) + xtnsize, &dev_pro_methods, &dev_pro_event_callbacks, (void*)info); } diff --git a/mio/lib/mio-sck.c b/mio/lib/mio-sck.c index ed81734..e3b0276 100644 --- a/mio/lib/mio-sck.c +++ b/mio/lib/mio-sck.c @@ -1350,7 +1350,7 @@ accept_done: * instead of MIO_SIZEOF(mio_dev_sck_t). therefore, the * extension area as big as that of the master sck device * is created in the client sck device */ - clidev = (mio_dev_sck_t*)mio_makedev(mio, rdev->dev_size, &dev_mth_clisck, rdev->dev_evcb, &clisck); + clidev = (mio_dev_sck_t*)mio_dev_make(mio, rdev->dev_size, &dev_mth_clisck, rdev->dev_evcb, &clisck); if (!clidev) { close (clisck); @@ -1699,13 +1699,13 @@ mio_dev_sck_t* mio_dev_sck_make (mio_t* mio, mio_oow_t xtnsize, const mio_dev_sc if (sck_type_map[info->type].extra_dev_cap & MIO_DEV_CAP_STREAM) /* can't use the IS_STATEFUL() macro yet */ { - rdev = (mio_dev_sck_t*)mio_makedev( + rdev = (mio_dev_sck_t*)mio_dev_make( mio, MIO_SIZEOF(mio_dev_sck_t) + xtnsize, &dev_sck_methods_stateful, &dev_sck_event_callbacks_stateful, (void*)info); } else { - rdev = (mio_dev_sck_t*)mio_makedev( + rdev = (mio_dev_sck_t*)mio_dev_make( mio, MIO_SIZEOF(mio_dev_sck_t) + xtnsize, &dev_sck_methods_stateless, &dev_sck_event_callbacks_stateless, (void*)info); } diff --git a/mio/lib/mio.c b/mio/lib/mio.c index d690442..d2712e3 100644 --- a/mio/lib/mio.c +++ b/mio/lib/mio.c @@ -47,6 +47,9 @@ static int kill_and_free_device (mio_dev_t* dev, int force); } while (0) + + + static void on_read_timeout (mio_t* mio, const mio_ntime_t* now, mio_tmrjob_t* job); static void on_write_timeout (mio_t* mio, const mio_ntime_t* now, mio_tmrjob_t* job); @@ -149,6 +152,20 @@ void mio_fini (mio_t* mio) } } + while (mio->actsvc.head) + { + if (mio->actsvc.head->stop) + { + /* the stop callback must unregister itself */ + mio->actsvc.head->stop (mio->actsvc.head); + } + else + { + /* unregistration only if no stop callback is designated */ + MIO_SVC_UNREGISTER (mio, mio->actsvc.head); + } + } + /* kill all registered devices */ while (mio->actdev.head) { @@ -613,7 +630,7 @@ int mio_loop (mio_t* mio) return 0; } -mio_dev_t* mio_makedev (mio_t* mio, mio_oow_t dev_size, mio_dev_mth_t* dev_mth, mio_dev_evcb_t* dev_evcb, void* make_ctx) +mio_dev_t* mio_dev_make (mio_t* mio, mio_oow_t dev_size, mio_dev_mth_t* dev_mth, mio_dev_evcb_t* dev_evcb, void* make_ctx) { mio_dev_t* dev; diff --git a/mio/lib/mio.h b/mio/lib/mio.h index 2e0328d..e99372e 100644 --- a/mio/lib/mio.h +++ b/mio/lib/mio.h @@ -55,6 +55,7 @@ typedef struct mio_t mio_t; typedef struct mio_dev_t mio_dev_t; typedef struct mio_dev_mth_t mio_dev_mth_t; typedef struct mio_dev_evcb_t mio_dev_evcb_t; +typedef struct mio_svc_t mio_svc_t; typedef struct mio_q_t mio_q_t; typedef struct mio_wq_t mio_wq_t; @@ -156,11 +157,11 @@ struct mio_tmrjob_t struct mio_dev_mth_t { /* ------------------------------------------------------------------ */ - /* mandatory. called in mio_makedev() */ + /* mandatory. called in mio_dev_make() */ int (*make) (mio_dev_t* dev, void* ctx); /* ------------------------------------------------------------------ */ - /* mandatory. called in mio_dev_kill(). also called in mio_makedev() upon + /* mandatory. called in mio_dev_kill(). also called in mio_dev_make() upon * failure after make() success. * * when 'force' is 0, the return value of -1 causes the device to be a @@ -175,7 +176,7 @@ struct mio_dev_mth_t int (*kill) (mio_dev_t* dev, int force); /* ------------------------------------------------------------------ */ - mio_syshnd_t (*getsyshnd) (mio_dev_t* dev); /* mandatory. called in mio_makedev() after successful make() */ + mio_syshnd_t (*getsyshnd) (mio_dev_t* dev); /* mandatory. called in mio_dev_make() after successful make() */ /* ------------------------------------------------------------------ */ @@ -382,6 +383,45 @@ typedef enum mio_dev_event_t mio_dev_event_t; #define MIO_CWQFL_SIZE 16 #define MIO_CWQFL_ALIGN 16 + +/* ========================================================================= + * SERVICE + * ========================================================================= */ + +typedef void (*mio_svc_stop_t) (mio_svc_t* svc); + +#define MIO_SVC_HEADERS \ + mio_t* mio; \ + mio_svc_stop_t stop; \ + mio_svc_t* svc_prev; \ + mio_svc_t* svc_next + +/* the stop callback is called if it's not NULL and the service is still + * alive when mio_close() is reached. it still calls MIO_SVC_UNREGISTER() + * if the stop callback is NULL. The stop callback, if specified, must + * call MIO_SVC_UNREGISTER(). */ + +struct mio_svc_t +{ + MIO_SVC_HEADERS; +}; + +#define MIO_SVC_REGISTER(mio,svc) do { \ + if ((mio)->actsvc.tail) (mio)->actsvc.tail->svc_next = (svc); \ + else (mio)->actsvc.head = (svc); \ + (svc)->svc_prev = (mio)->actsvc.tail; \ + (svc)->svc_next = MIO_NULL; \ + (mio)->actsvc.tail = (svc); \ +} while(0) + +#define MIO_SVC_UNREGISTER(mio,svc) do { \ + if ((svc)->svc_prev) (svc)->svc_prev->svc_next = (svc)->svc_next; \ + else (mio)->actsvc.head = (svc)->svc_next; \ + if ((svc)->svc_next) (svc)->svc_next->svc_prev = (svc)->svc_prev; \ + else (mio)->actsvc.tail = (svc)->svc_prev; \ +} while (0) + + /* ========================================================================= * MIO LOGGING * ========================================================================= */ @@ -545,6 +585,12 @@ struct mio_t mio_cwq_t cwq; mio_cwq_t* cwqfl[MIO_CWQFL_SIZE]; /* list of free cwq objects */ + struct + { + mio_svc_t* head; + mio_svc_t* tail; + } actsvc; /* active services */ + /* platform specific fields below */ mio_sys_t* sysdep; }; @@ -680,7 +726,9 @@ MIO_EXPORT void mio_stop ( mio_stopreq_t stopreq ); -MIO_EXPORT mio_dev_t* mio_makedev ( + + +MIO_EXPORT mio_dev_t* mio_dev_make ( mio_t* mio, mio_oow_t dev_size, mio_dev_mth_t* dev_mth,