diff --git a/mio/bin/t01.c b/mio/bin/t01.c index c3e9115..e185b9a 100644 --- a/mio/bin/t01.c +++ b/mio/bin/t01.c @@ -76,18 +76,31 @@ printf ("CRITICAL ERROR ---> too many heap chunks...\n"); } x = malloc (size); - if (x) ((mmgr_stat_t*)mmgr->ctx)->total_count++; + if (x) + { + ((mmgr_stat_t*)mmgr->ctx)->total_count++; + /*printf ("MMGR total_count INCed to %d => %p\n", ((mmgr_stat_t*)mmgr->ctx)->total_count, x);*/ + } return x; } static void* mmgr_realloc (mio_mmgr_t* mmgr, void* ptr, mio_oow_t size) { - return realloc (ptr, size); + void* x; + + x = realloc (ptr, size); + if (x && !ptr) + { + ((mmgr_stat_t*)mmgr->ctx)->total_count++; + /*printf ("MMGR total_count INCed to %d => %p\n", ((mmgr_stat_t*)mmgr->ctx)->total_count, x);*/ + } + return x; } static void mmgr_free (mio_mmgr_t* mmgr, void* ptr) { ((mmgr_stat_t*)mmgr->ctx)->total_count--; + /*printf ("MMGR total_count DECed to %d => %p\n", ((mmgr_stat_t*)mmgr->ctx)->total_count, ptr);*/ return free (ptr); } @@ -889,8 +902,8 @@ int main (int argc, char* argv[]) tcp_bind.options |= MIO_DEV_SCK_BIND_SSL; tcp_bind.ssl_certfile = "localhost.crt"; tcp_bind.ssl_keyfile = "localhost.key"; + MIO_INIT_NTIME (&tcp_bind.ssl_accept_tmout, 5, 1); #endif - MIO_INIT_NTIME (&tcp_bind.accept_tmout, 5, 1); if (mio_dev_sck_bind(tcp[2], &tcp_bind) <= -1) { diff --git a/mio/lib/dns-cli.c b/mio/lib/dns-cli.c index ce3d266..294ba5e 100644 --- a/mio/lib/dns-cli.c +++ b/mio/lib/dns-cli.c @@ -297,7 +297,7 @@ static int on_tcp_read (mio_dev_sck_t* dev, const void* data, mio_iolen_t dlen, return 0; oops: - mio_dev_sck_halt(dev); + mio_dev_sck_halt (dev); return 0; } diff --git a/mio/lib/http-svr.c b/mio/lib/http-svr.c index dd14fae..7c044db 100644 --- a/mio/lib/http-svr.c +++ b/mio/lib/http-svr.c @@ -344,6 +344,8 @@ static void client_on_disconnect (mio_dev_sck_t* sck) sck_xtn_t* sckxtn = mio_dev_sck_getxtn(sck); printf ("** HTTS - client disconnect %p\n", sck); fini_client (sck->mio, &sckxtn->c); + + /* TODO: remove it from the list of clients */ } /* ------------------------------------------------------------------------ */ @@ -410,15 +412,15 @@ static void listener_on_disconnect (mio_dev_sck_t* sck) break; case MIO_DEV_SCK_ACCEPTING_SSL: - MIO_INFO1 (sck->mio, "INCOMING SSL-ACCEPT GOT DISCONNECTED(%d) ....\n", (int)sck->sck); + MIO_INFO1 (sck->mio, "LISTENER INCOMING SSL-ACCEPT GOT DISCONNECTED(%d) ....\n", (int)sck->sck); break; case MIO_DEV_SCK_ACCEPTED: - MIO_INFO1 (sck->mio, "INCOMING CLIENT BEING SERVED GOT DISCONNECTED(%d).......\n", (int)sck->sck); + MIO_INFO1 (sck->mio, "LISTENER INCOMING CLIENT BEING SERVED GOT DISCONNECTED(%d).......\n", (int)sck->sck); break; default: - MIO_INFO1 (sck->mio, "DISCONNECTED AFTER ALL(%d).......\n", (int)sck->sck); + MIO_INFO1 (sck->mio, "LISTENER DISCONNECTED AFTER ALL(%d).......\n", (int)sck->sck); break; } @@ -427,6 +429,8 @@ static void listener_on_disconnect (mio_dev_sck_t* sck) * for a listener socket, these fields must be NULL */ MIO_ASSERT (sck->mio, sckxtn->c.htrd == MIO_NULL); MIO_ASSERT (sck->mio, sckxtn->c.sbuf == MIO_NULL); + + sckxtn->htts->lsck = MIO_NULL; /* let the htts service forget about this listening socket */ } @@ -478,8 +482,8 @@ mio_svc_htts_t* mio_svc_htts_start (mio_t* mio, const mio_skad_t* bind_addr) MIO_MEMSET (&info, 0, MIO_SIZEOF(info)); info.b.localaddr = *bind_addr; - info.b.options = MIO_DEV_SCK_BIND_REUSEADDR | MIO_DEV_SCK_BIND_REUSEPORT; - MIO_INIT_NTIME (&info.b.accept_tmout, 5, 1); + info.b.options = MIO_DEV_SCK_BIND_REUSEADDR | MIO_DEV_SCK_BIND_REUSEPORT | MIO_DEV_SCK_BIND_LENIENT; + /*MIO_INIT_NTIME (&info.b.ssl_accept_tmout, 5, 1);*/ if (mio_dev_sck_bind(htts->lsck, &info.b) <= -1) goto oops; info.l.backlogs = 255; diff --git a/mio/lib/mio-sck.h b/mio/lib/mio-sck.h index a2f4495..e111d96 100644 --- a/mio/lib/mio-sck.h +++ b/mio/lib/mio-sck.h @@ -221,6 +221,8 @@ typedef enum mio_dev_sck_ioctl_cmd_t mio_dev_sck_ioctl_cmd_t; } while(0) #define MIO_DEV_SCK_GET_PROGRESS(dev) ((dev)->state & MIO_DEV_SCK_ALL_PROGRESS_BITS) +#define MIO_DEV_SCK_GET_TOLERANT(dev) ((dev)->state & MIO_DEV_SCK_ + enum mio_dev_sck_state_t { @@ -233,9 +235,9 @@ enum mio_dev_sck_state_t MIO_DEV_SCK_ACCEPTED = (1 << 5), /* the following items can be bitwise-ORed with an exclusive item above */ + MIO_DEV_SCK_LENIENT = (1 << 14), MIO_DEV_SCK_INTERCEPTED = (1 << 15), - /* convenience bit masks */ MIO_DEV_SCK_ALL_PROGRESS_BITS = (MIO_DEV_SCK_CONNECTING | MIO_DEV_SCK_CONNECTING_SSL | @@ -313,6 +315,7 @@ enum mio_dev_sck_bind_option_t /* TODO: more options --- SO_RCVBUF, SO_SNDBUF, SO_RCVTIMEO, SO_SNDTIMEO, SO_KEEPALIVE */ /* BINDTODEVICE??? */ + MIO_DEV_SCK_BIND_LENIENT = (1 << 14), /* for now, accept failure doesn't affect the listing socket if this is set */ MIO_DEV_SCK_BIND_SSL = (1 << 15) }; typedef enum mio_dev_sck_bind_option_t mio_dev_sck_bind_option_t; @@ -320,18 +323,18 @@ typedef enum mio_dev_sck_bind_option_t mio_dev_sck_bind_option_t; typedef struct mio_dev_sck_bind_t mio_dev_sck_bind_t; struct mio_dev_sck_bind_t { - int options; + int options; /** 0 or bitwise-OR'ed of mio_dev_sck_bind_option_t enumerators */ mio_skad_t localaddr; /* TODO: add device name for BIND_TO_DEVICE */ const mio_bch_t* ssl_certfile; const mio_bch_t* ssl_keyfile; - mio_ntime_t accept_tmout; + mio_ntime_t ssl_accept_tmout; }; enum mio_dev_sck_connect_option_t { - MIO_DEV_SCK_CONNECT_SSL = (1 << 15) + MIO_DEV_SCK_CONNECT_SSL = (1 << 15) }; typedef enum mio_dev_sck_connect_option_t mio_dev_sck_connect_option_t; @@ -349,14 +352,6 @@ struct mio_dev_sck_listen_t int backlogs; }; -typedef struct mio_dev_sck_accept_t mio_dev_sck_accept_t; -struct mio_dev_sck_accept_t -{ - mio_syshnd_t sck; -/* TODO: add timeout */ - mio_skad_t remoteaddr; -}; - struct mio_dev_sck_t { MIO_DEV_HEADER; diff --git a/mio/lib/mio.c b/mio/lib/mio.c index ce59419..1678ad7 100644 --- a/mio/lib/mio.c +++ b/mio/lib/mio.c @@ -179,6 +179,7 @@ void mio_fini (mio_t* mio) } } + /* kill services before killing devices */ while (!MIO_SVCL_IS_EMPTY(&mio->actsvc)) { mio_svc_t* svc; @@ -751,7 +752,6 @@ static int kill_and_free_device (mio_dev_t* dev, int force) MIO_ASSERT (mio, !(dev->dev_cap & MIO_DEV_CAP_ACTIVE)); MIO_ASSERT (mio, !(dev->dev_cap & MIO_DEV_CAP_HALTED)); - if (dev->dev_mth->kill(dev, force) <= -1) { if (force >= 2) goto free_device; @@ -909,6 +909,8 @@ void mio_dev_halt (mio_dev_t* dev) if (dev->dev_cap & MIO_DEV_CAP_ACTIVE) { + MIO_DEBUG1 (mio, "HALTING DEVICE %p\n", dev); + /* delink the device object from the active device list */ MIO_DEVL_UNLINK_DEV (dev); dev->dev_cap &= ~MIO_DEV_CAP_ACTIVE; @@ -1160,6 +1162,11 @@ static int __dev_write (mio_dev_t* dev, const void* data, mio_iolen_t len, const } else { + /* the write callback should return at most the number of requested + * bytes. but returning more is harmless as urem is of a signed type. + * for a zero-length request, it's necessary to return at least 1 + * to indicate successful acknowlegement. otherwise, it gets enqueued + * as shown in the 'if' block right above. */ urem -= ulen; uptr += ulen; } diff --git a/mio/lib/mio.h b/mio/lib/mio.h index c87aa79..96208a2 100644 --- a/mio/lib/mio.h +++ b/mio/lib/mio.h @@ -360,7 +360,6 @@ struct mio_dev_t (dev)->dev_next->dev_prev = (dev)->dev_prev; \ } while (0) - #define MIO_DEVL_INIT(lh) ((lh)->dev_next = (lh)->dev_prev = lh) #define MIO_DEVL_FIRST_DEV(lh) ((lh)->dev_next) #define MIO_DEVL_LAST_DEV(lh) ((lh)->dev_prev) diff --git a/mio/lib/sck.c b/mio/lib/sck.c index e53e8ef..53a3fd6 100644 --- a/mio/lib/sck.c +++ b/mio/lib/sck.c @@ -517,14 +517,17 @@ static int dev_sck_write_stateful (mio_dev_t* dev, const void* data, mio_iolen_t if (*len <= 0) { - /* it's a writing finish indicator. close the writing end of - * the socket, probably leaving it in the half-closed state */ + /* the write handler for a stream device must handle a zero-length + * writing request specially. it's a writing finish indicator. close + * the writing end of the socket, probably leaving it in the half-closed state */ if (shutdown(rdev->sck, SHUT_WR) == -1) { mio_seterrwithsyserr (mio, 0, errno); return -1; } + /* it must return a non-zero positive value. if it returns 0, this request + * gets enqueued by the core. we must aovid it */ return 1; } @@ -658,14 +661,13 @@ static int dev_sck_write_stateless (mio_dev_t* dev, const void* data, mio_iolen_ return 1; } - static int dev_sck_writev_stateless (mio_dev_t* dev, const mio_iovec_t* iov, mio_iolen_t* iovcnt, const mio_devaddr_t* dstaddr) { mio_t* mio = dev->mio; mio_dev_sck_t* rdev = (mio_dev_sck_t*)dev; struct msghdr msg; ssize_t x; - + MIO_MEMSET (&msg, 0, MIO_SIZEOF(msg)); if (MIO_LIKELY(dstaddr)) { @@ -900,7 +902,7 @@ static int dev_sck_ioctl (mio_dev_t* dev, int cmd, void* arg) SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2); /* no outdated SSLv2 by default */ - rdev->tmout = bnd->accept_tmout; + rdev->tmout = bnd->ssl_accept_tmout; #else mio_seterrnum (mio, MIO_ENOIMPL); return -1; @@ -923,6 +925,7 @@ static int dev_sck_ioctl (mio_dev_t* dev, int cmd, void* arg) rdev->ssl_ctx = ssl_ctx; #endif + if (bnd->options & MIO_DEV_SCK_BIND_LENIENT) rdev->state |= MIO_DEV_SCK_LENIENT; return 0; } @@ -931,7 +934,6 @@ static int dev_sck_ioctl (mio_dev_t* dev, int cmd, void* arg) mio_dev_sck_connect_t* conn = (mio_dev_sck_connect_t*)arg; struct sockaddr* sa = (struct sockaddr*)&conn->remoteaddr; mio_scklen_t sl; - mio_skad_t localaddr; int x; #if defined(USE_SSL) SSL_CTX* ssl_ctx = MIO_NULL; @@ -1488,7 +1490,16 @@ static int dev_evcb_sck_ready_stateful (mio_dev_t* dev, int events) } else if (events & MIO_DEV_EVENT_IN) { - return accept_incoming_connection(rdev); + if (rdev->state & MIO_DEV_SCK_LENIENT) + { + accept_incoming_connection(rdev); + return 0; /* return ok to the core regardless of accept()'s result */ + } + else + { + /* [NOTE] if the accept operation fails, the core also kills this listening device. */ + return accept_incoming_connection(rdev); + } } else {