diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/aio.c | 150 | ||||
| -rw-r--r-- | src/core/aio.h | 96 | ||||
| -rw-r--r-- | src/core/defs.h | 4 | ||||
| -rw-r--r-- | src/core/device.c | 8 | ||||
| -rw-r--r-- | src/core/endpt.c | 10 | ||||
| -rw-r--r-- | src/core/msgqueue.c | 6 | ||||
| -rw-r--r-- | src/core/msgqueue.h | 4 | ||||
| -rw-r--r-- | src/core/pipe.c | 12 | ||||
| -rw-r--r-- | src/core/pipe.h | 4 | ||||
| -rw-r--r-- | src/core/protocol.h | 4 | ||||
| -rw-r--r-- | src/core/socket.c | 20 | ||||
| -rw-r--r-- | src/core/socket.h | 6 | ||||
| -rw-r--r-- | src/core/transport.c | 1 | ||||
| -rw-r--r-- | src/core/url.c | 5 | ||||
| -rw-r--r-- | src/core/url.h | 1 |
15 files changed, 201 insertions, 130 deletions
diff --git a/src/core/aio.c b/src/core/aio.c index a036a606..341b218e 100644 --- a/src/core/aio.c +++ b/src/core/aio.c @@ -54,6 +54,57 @@ static nni_list nni_aio_expire_aios; // if it comes back nonzero (NNG_ESTATE) then it must simply discard the // request and return. +// An nni_aio is an async I/O handle. +struct nng_aio { + int a_result; // Result code (nng_errno) + size_t a_count; // Bytes transferred (I/O only) + nni_time a_expire; // Absolute timeout + nni_duration a_timeout; // Relative timeout + + // These fields are private to the aio framework. + nni_cv a_cv; + unsigned a_fini : 1; // shutting down (no new operations) + unsigned a_done : 1; // operation has completed + unsigned a_pend : 1; // completion routine pending + unsigned a_active : 1; // aio was started + unsigned a_expiring : 1; // expiration callback in progress + unsigned a_waiting : 1; // a thread is waiting for this to finish + unsigned a_synch : 1; // run completion synchronously + nni_task a_task; + + // Read/write operations. + nni_iov *a_iov; + int a_niov; + nni_iov a_iovinl[4]; // inline IOVs - when the IOV list is short + nni_iov *a_iovalloc; // dynamically allocated IOVs + int a_niovalloc; // number of allocated IOVs + + // Message operations. + nni_msg *a_msg; + + // Connect/accept operations. + void *a_pipe; // opaque pipe handle + + // User scratch data. Consumers may store values here, which + // must be preserved by providers and the framework. + void *a_user_data[4]; + + // Operation inputs & outputs. Up to 4 inputs and 4 outputs may be + // specified. The semantics of these will vary, and depend on the + // specific operation. + void *a_inputs[4]; + void *a_outputs[4]; + + // Provider-use fields. + nni_aio_cancelfn a_prov_cancel; + void * a_prov_data; + nni_list_node a_prov_node; + void * a_prov_extra[4]; // Extra data used by provider + + // Expire node. + nni_list_node a_expire_node; +}; + static void nni_aio_expire_add(nni_aio *); int @@ -88,7 +139,7 @@ nni_aio_fini(nni_aio *aio) nni_cv_fini(&aio->a_cv); if (aio->a_niovalloc > 0) { - NNI_FREE_STRUCTS(aio->a_iov, aio->a_niovalloc); + NNI_FREE_STRUCTS(aio->a_iovalloc, aio->a_niovalloc); } NNI_FREE_STRUCT(aio); @@ -96,21 +147,27 @@ nni_aio_fini(nni_aio *aio) } int -nni_aio_set_iov(nni_aio *aio, int niov, nng_iov *iov) +nni_aio_set_iov(nni_aio *aio, int niov, const nni_iov *iov) { - if ((niov > 4) && (niov > aio->a_niovalloc)) { + if ((niov > NNI_NUM_ELEMENTS(aio->a_iovinl)) && + (niov > aio->a_niovalloc)) { nni_iov *newiov = NNI_ALLOC_STRUCTS(newiov, niov); if (newiov == NULL) { return (NNG_ENOMEM); } if (aio->a_niovalloc > 0) { - NNI_FREE_STRUCTS(aio->a_iov, aio->a_niovalloc); + NNI_FREE_STRUCTS(aio->a_iovalloc, aio->a_niovalloc); } aio->a_iov = newiov; + aio->a_iovalloc = newiov; aio->a_niovalloc = niov; } - - memcpy(aio->a_iov, iov, niov * sizeof(nng_iov)); + if (niov <= NNI_NUM_ELEMENTS(aio->a_iovinl)) { + aio->a_iov = aio->a_iovinl; + } else { + aio->a_iov = aio->a_iovalloc; + } + memcpy(aio->a_iov, iov, niov * sizeof(nni_iov)); aio->a_niov = niov; return (0); } @@ -136,7 +193,7 @@ nni_aio_stop(nni_aio *aio) aio->a_fini = 1; nni_mtx_unlock(&nni_aio_lk); - nni_aio_cancel(aio, NNG_ECANCELED); + nni_aio_abort(aio, NNG_ECANCELED); nni_aio_wait(aio); } @@ -293,10 +350,10 @@ nni_aio_start(nni_aio *aio, nni_aio_cancelfn cancelfn, void *data) return (0); } -// nni_aio_cancel is called by a consumer which guarantees that the aio +// nni_aio_abort is called by a consumer which guarantees that the aio // is still valid. void -nni_aio_cancel(nni_aio *aio, int rv) +nni_aio_abort(nni_aio *aio, int rv) { nni_aio_cancelfn cancelfn; @@ -502,6 +559,81 @@ nni_aio_expire_loop(void *arg) } } +void * +nni_aio_get_prov_data(nni_aio *aio) +{ + return (aio->a_prov_data); +} + +void +nni_aio_set_prov_data(nni_aio *aio, void *data) +{ + aio->a_prov_data = data; +} + +void * +nni_aio_get_prov_extra(nni_aio *aio, unsigned index) +{ + return (aio->a_prov_extra[index]); +} + +void +nni_aio_set_prov_extra(nni_aio *aio, unsigned index, void *data) +{ + aio->a_prov_extra[index] = data; +} + +void +nni_aio_get_iov(nni_aio *aio, int *niovp, nni_iov **iovp) +{ + *niovp = aio->a_niov; + *iovp = aio->a_iov; +} + +void +nni_aio_normalize_timeout(nni_aio *aio, nng_duration dur) +{ + if (aio->a_timeout == NNG_DURATION_DEFAULT) { + aio->a_timeout = dur; + } +} + +void +nni_aio_bump_count(nni_aio *aio, size_t n) +{ + aio->a_count += n; +} + +size_t +nni_aio_iov_count(nni_aio *aio) +{ + size_t resid = 0; + + for (int i = 0; i < aio->a_niov; i++) { + resid += aio->a_iov[i].iov_len; + } + return (resid); +} + +size_t +nni_aio_iov_advance(nni_aio *aio, size_t n) +{ + size_t resid = n; + while (n) { + NNI_ASSERT(aio->a_niov != 0); + if (aio->a_iov[0].iov_len > n) { + aio->a_iov[0].iov_len -= n; + NNI_INCPTR(aio->a_iov[0].iov_buf, n); + return (0); // we used all of "n" + } + resid -= aio->a_iov[0].iov_len; + n -= aio->a_iov[0].iov_len; + aio->a_iov = &aio->a_iov[1]; + aio->a_niov--; + } + return (resid); // we might not have used all of n for this iov +} + void nni_aio_sys_fini(void) { diff --git a/src/core/aio.h b/src/core/aio.h index 33fe07cb..34f4a56b 100644 --- a/src/core/aio.h +++ b/src/core/aio.h @@ -20,59 +20,6 @@ typedef struct nni_aio_ops nni_aio_ops; typedef void (*nni_aio_cancelfn)(nni_aio *, int); -// An nni_aio is an async I/O handle. -struct nni_aio { - int a_result; // Result code (nng_errno) - size_t a_count; // Bytes transferred (I/O only) - nni_time a_expire; // Absolute timeout - nni_duration a_timeout; // Relative timeout - - // These fields are private to the aio framework. - nni_cv a_cv; - unsigned a_fini : 1; // shutting down (no new operations) - unsigned a_done : 1; // operation has completed - unsigned a_pend : 1; // completion routine pending - unsigned a_active : 1; // aio was started - unsigned a_expiring : 1; // expiration callback in progress - unsigned a_waiting : 1; // a thread is waiting for this to finish - unsigned a_synch : 1; // run completion synchronously - nni_task a_task; - - // Read/write operations. - nni_iov *a_iov; - int a_niov; - nni_iov a_iovinl[4]; // inline IOVs - when the IOV list is short - int a_niovalloc; // number of allocated IOVs - - // Message operations. - nni_msg *a_msg; - - // Connect/accept operations. - void *a_pipe; // opaque pipe handle - - // Resolver operations. - nni_sockaddr *a_addr; - - // User scratch data. Consumers may store values here, which - // must be preserved by providers and the framework. - void *a_user_data[4]; - - // Operation inputs & outputs. Up to 4 inputs and 4 outputs may be - // specified. The semantics of these will vary, and depend on the - // specific operation. - void *a_inputs[4]; - void *a_outputs[4]; - - // Provider-use fields. - nni_aio_cancelfn a_prov_cancel; - void * a_prov_data; - nni_list_node a_prov_node; - void * a_prov_extra[4]; // Extra data used by provider - - // Expire node. - nni_list_node a_expire_node; -}; - // nni_aio_init initializes an aio object. The callback is called with // the supplied argument when the operation is complete. If NULL is // supplied for the callback, then nni_aio_wake is used in its place, @@ -128,11 +75,6 @@ extern void nni_aio_set_output(nni_aio *, int, void *); // nni_get_output returns an output previously stored on the AIO. extern void *nni_aio_get_output(nni_aio *, int); -// nni_aio_set_iov sets an IOV (scatter/gather vector) on the AIO. -// Up to 4 may be set without any possibility of failure, more than that -// may require an allocation and hence fail due to NNG_ENOMEM. -extern int nni_aio_set_iov(nni_aio *, int, nng_iov *); - // XXX: These should be refactored in terms of generic inputs and outputs. extern void nni_aio_set_msg(nni_aio *, nni_msg *); extern nni_msg *nni_aio_get_msg(nni_aio *); @@ -152,11 +94,6 @@ extern void * nni_aio_get_pipe(nni_aio *); // completion callback. void nni_aio_set_synch(nni_aio *); -// nni_aio_set_timeout sets the timeout (relative) when the AIO will -// be canceled. The cancelation does not happen until after nni_aio_start -// is called. -extern void nni_aio_set_timeout(nni_aio *, nni_duration); - // nni_aio_result returns the result code (0 on success, or an NNG errno) // for the operation. It is only valid to call this when the operation is // complete (such as when the callback is executed or after nni_aio_wait @@ -192,19 +129,30 @@ extern void nni_aio_finish_error(nni_aio *, int); extern void nni_aio_finish_pipe(nni_aio *, void *); extern void nni_aio_finish_msg(nni_aio *, nni_msg *); -// nni_aio_cancel is used to cancel an operation. Any pending I/O or +// nni_aio_abort is used to abort an operation. Any pending I/O or // timeouts are canceled if possible, and the callback will be returned // with the indicated result (NNG_ECLOSED or NNG_ECANCELED is recommended.) -extern void nni_aio_cancel(nni_aio *, int rv); - -extern int nni_aio_start(nni_aio *, nni_aio_cancelfn, void *); - -// nni_aio_stop is used to abort all further operations on the AIO. -// When this is executed, no further operations or callbacks will be -// executed, and if callbacks or I/O is in progress this will block -// until they are either canceled or aborted. (Question: why not just -// nni_fini?) -// extern void nni_aio_stop(nni_aio *); +extern void nni_aio_abort(nni_aio *, int rv); + +extern int nni_aio_start(nni_aio *, nni_aio_cancelfn, void *); +extern void *nni_aio_get_prov_data(nni_aio *); +extern void nni_aio_set_prov_data(nni_aio *, void *); +extern void *nni_aio_get_prov_extra(nni_aio *, unsigned); +extern void nni_aio_set_prov_extra(nni_aio *, unsigned, void *); +// nni_aio_advance_iov moves up the iov, reflecting that some I/O as +// been performed. It returns the amount of data remaining in the argument; +// i.e. if the count refers to more data than the iov can support, then +// the result will be left over count. +extern size_t nni_aio_iov_advance(nni_aio *, size_t); +// nni_aio_iov_count returns the number of bytes referenced by the aio's iov. +extern size_t nni_aio_iov_count(nni_aio *); + +extern int nni_aio_set_iov(nni_aio *, int, const nni_iov *); + +extern void nni_aio_set_timeout(nni_aio *, nng_duration); +extern void nni_aio_get_iov(nni_aio *, int *, nni_iov **); +extern void nni_aio_normalize_timeout(nni_aio *, nng_duration); +extern void nni_aio_bump_count(nni_aio *, size_t); extern int nni_aio_sys_init(void); extern void nni_aio_sys_fini(void); diff --git a/src/core/defs.h b/src/core/defs.h index fbf074b4..dbbccf58 100644 --- a/src/core/defs.h +++ b/src/core/defs.h @@ -30,12 +30,14 @@ #define NNI_NUM_ELEMENTS(x) (sizeof(x) / sizeof((x)[0])) // These types are common but have names shared with user space. +// Internal code should use these names when possible. typedef struct nng_msg nni_msg; typedef struct nng_sockaddr nni_sockaddr; typedef struct nng_event nni_event; typedef struct nng_notify nni_notify; typedef struct nng_url nni_url; typedef struct nng_iov nni_iov; +typedef struct nng_aio nni_aio; // These are our own names. typedef struct nni_socket nni_sock; @@ -62,8 +64,6 @@ typedef int nni_signal; // Wakeup channel. typedef uint64_t nni_time; // Abs. time (ms). typedef int32_t nni_duration; // Rel. time (ms). -typedef struct nni_aio nni_aio; - typedef void (*nni_cb)(void *); // Notify descriptor. diff --git a/src/core/device.c b/src/core/device.c index e6b75897..0eaec30e 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -1,6 +1,6 @@ // -// Copyright 2017 Garrett D'Amore <garrett@damore.org> -// Copyright 2017 Capitar IT Group BV <info@capitar.com> +// Copyright 2018 Staysail Systems, Inc. <info@staysail.com> +// Copyright 2018 Capitar IT Group BV <info@capitar.com> // // This software is supplied under the terms of the MIT License, a // copy of which should be located in the distribution where this @@ -38,7 +38,7 @@ typedef struct nni_device_pair nni_device_pair; static void nni_device_cancel(nni_aio *aio, int rv) { - nni_device_data *dd = aio->a_prov_data; + nni_device_data *dd = nni_aio_get_prov_data(aio); // cancellation is the only path to shutting it down. nni_mtx_lock(&dd->mtx); @@ -63,7 +63,7 @@ nni_device_cb(void *arg) if ((rv = nni_aio_result(aio)) != 0) { p->state = NNI_DEVICE_STATE_FINI; - nni_aio_cancel(p->user, rv); + nni_aio_abort(p->user, rv); return; } diff --git a/src/core/endpt.c b/src/core/endpt.c index cfabcc87..4a2c3097 100644 --- a/src/core/endpt.c +++ b/src/core/endpt.c @@ -249,10 +249,10 @@ nni_ep_shutdown(nni_ep *ep) nni_mtx_unlock(&ep->ep_mtx); // Abort any remaining in-flight operations. - nni_aio_cancel(ep->ep_acc_aio, NNG_ECLOSED); - nni_aio_cancel(ep->ep_con_aio, NNG_ECLOSED); - nni_aio_cancel(ep->ep_con_syn, NNG_ECLOSED); - nni_aio_cancel(ep->ep_tmo_aio, NNG_ECLOSED); + nni_aio_abort(ep->ep_acc_aio, NNG_ECLOSED); + nni_aio_abort(ep->ep_con_aio, NNG_ECLOSED); + nni_aio_abort(ep->ep_con_syn, NNG_ECLOSED); + nni_aio_abort(ep->ep_tmo_aio, NNG_ECLOSED); // Stop the underlying transport. ep->ep_ops.ep_close(ep->ep_data); @@ -296,7 +296,7 @@ nni_ep_close(nni_ep *ep) static void nni_ep_tmo_cancel(nni_aio *aio, int rv) { - nni_ep *ep = aio->a_prov_data; + nni_ep *ep = nni_aio_get_prov_data(aio); // The only way this ever gets "finished", is via cancellation. if (ep != NULL) { nni_mtx_lock(&ep->ep_mtx); diff --git a/src/core/msgqueue.c b/src/core/msgqueue.c index 10bffaa4..de4708fe 100644 --- a/src/core/msgqueue.c +++ b/src/core/msgqueue.c @@ -1,6 +1,6 @@ // -// Copyright 2017 Garrett D'Amore <garrett@damore.org> -// Copyright 2017 Capitar IT Group BV <info@capitar.com> +// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2018 Capitar IT Group BV <info@capitar.com> // // This software is supplied under the terms of the MIT License, a // copy of which should be located in the distribution where this @@ -338,7 +338,7 @@ nni_msgq_set_cb(nni_msgq *mq, nni_msgq_cb fn, void *arg) static void nni_msgq_cancel(nni_aio *aio, int rv) { - nni_msgq *mq = aio->a_prov_data; + nni_msgq *mq = nni_aio_get_prov_data(aio); nni_mtx_lock(&mq->mq_lock); if (nni_aio_list_active(aio)) { diff --git a/src/core/msgqueue.h b/src/core/msgqueue.h index ececf372..9cc650e0 100644 --- a/src/core/msgqueue.h +++ b/src/core/msgqueue.h @@ -1,6 +1,6 @@ // -// Copyright 2017 Garrett D'Amore <garrett@damore.org> -// Copyright 2017 Capitar IT Group BV <info@capitar.com> +// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2018 Capitar IT Group BV <info@capitar.com> // // This software is supplied under the terms of the MIT License, a // copy of which should be located in the distribution where this diff --git a/src/core/pipe.c b/src/core/pipe.c index 66e7ae87..daee3834 100644 --- a/src/core/pipe.c +++ b/src/core/pipe.c @@ -201,7 +201,7 @@ nni_pipe_close(nni_pipe *p) nni_mtx_unlock(&p->p_mtx); // abort any pending negotiation/start process. - nni_aio_cancel(p->p_start_aio, NNG_ECLOSED); + nni_aio_abort(p->p_start_aio, NNG_ECLOSED); } void @@ -274,11 +274,11 @@ nni_pipe_create(nni_ep *ep, void *tdata) nni_mtx_init(&p->p_mtx); nni_cv_init(&p->p_cv, &nni_pipe_lk); - nni_aio_init(&p->p_start_aio, nni_pipe_start_cb, p); - - nni_mtx_lock(&nni_pipe_lk); - rv = nni_idhash_alloc(nni_pipes, &p->p_id, p); - nni_mtx_unlock(&nni_pipe_lk); + if ((rv = nni_aio_init(&p->p_start_aio, nni_pipe_start_cb, p)) == 0) { + nni_mtx_lock(&nni_pipe_lk); + rv = nni_idhash_alloc(nni_pipes, &p->p_id, p); + nni_mtx_unlock(&nni_pipe_lk); + } if ((rv != 0) || ((rv = nni_ep_pipe_add(ep, p)) != 0) || ((rv = nni_sock_pipe_add(sock, p)) != 0)) { diff --git a/src/core/pipe.h b/src/core/pipe.h index 54629810..32871335 100644 --- a/src/core/pipe.h +++ b/src/core/pipe.h @@ -1,6 +1,6 @@ // -// Copyright 2017 Garrett D'Amore <garrett@damore.org> -// Copyright 2017 Capitar IT Group BV <info@capitar.com> +// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2018 Capitar IT Group BV <info@capitar.com> // // This software is supplied under the terms of the MIT License, a // copy of which should be located in the distribution where this diff --git a/src/core/protocol.h b/src/core/protocol.h index 39bde059..47ddfd3f 100644 --- a/src/core/protocol.h +++ b/src/core/protocol.h @@ -1,6 +1,6 @@ // -// Copyright 2017 Garrett D'Amore <garrett@damore.org> -// Copyright 2017 Capitar IT Group BV <info@capitar.com> +// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2018 Capitar IT Group BV <info@capitar.com> // // This software is supplied under the terms of the MIT License, a // copy of which should be located in the distribution where this diff --git a/src/core/socket.c b/src/core/socket.c index 409e4f66..bf97ef8d 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -1,6 +1,6 @@ // -// Copyright 2017 Garrett D'Amore <garrett@damore.org> -// Copyright 2017 Capitar IT Group BV <info@capitar.com> +// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2018 Capitar IT Group BV <info@capitar.com> // // This software is supplied under the terms of the MIT License, a // copy of which should be located in the distribution where this @@ -126,7 +126,8 @@ nni_sock_getopt_fd(nni_sock *s, int flag, void *val, size_t *szp) cb = nni_sock_can_recv_cb; break; default: - nni_panic("default case!"); + // This should never occur. + return (NNG_EINVAL); } // If we already inited this, just give back the same file descriptor. @@ -772,25 +773,17 @@ nni_sock_closeall(void) } } -static void -nni_sock_normalize_expiration(nni_aio *aio, nni_duration def) -{ - if (aio->a_timeout == (nni_duration) -2) { - aio->a_timeout = def; - } -} - void nni_sock_send(nni_sock *sock, nni_aio *aio) { - nni_sock_normalize_expiration(aio, sock->s_sndtimeo); + nni_aio_normalize_timeout(aio, sock->s_sndtimeo); sock->s_sock_ops.sock_send(sock->s_data, aio); } void nni_sock_recv(nni_sock *sock, nni_aio *aio) { - nni_sock_normalize_expiration(aio, sock->s_rcvtimeo); + nni_aio_normalize_timeout(aio, sock->s_rcvtimeo); sock->s_sock_ops.sock_recv(sock->s_data, aio); } @@ -872,7 +865,6 @@ nni_sock_setopt(nni_sock *s, const char *name, const void *val, size_t size) { int rv = NNG_ENOTSUP; nni_ep * ep; - int commits = 0; nni_sockopt * optv; nni_sockopt * oldv = NULL; const nni_socket_option * sso; diff --git a/src/core/socket.h b/src/core/socket.h index 37c67436..30561d49 100644 --- a/src/core/socket.h +++ b/src/core/socket.h @@ -1,6 +1,6 @@ // -// Copyright 2017 Garrett D'Amore <garrett@damore.org> -// Copyright 2017 Capitar IT Group BV <info@capitar.com> +// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2018 Capitar IT Group BV <info@capitar.com> // // This software is supplied under the terms of the MIT License, a // copy of which should be located in the distribution where this @@ -39,7 +39,7 @@ extern uint32_t nni_sock_id(nni_sock *); // a pipe could wind up orphaned. extern int nni_sock_pipe_add(nni_sock *, nni_pipe *); extern void nni_sock_pipe_remove(nni_sock *, nni_pipe *); -extern int nni_sock_pipe_start(nni_sock *, nni_pipe *p); +extern int nni_sock_pipe_start(nni_sock *, nni_pipe *p); extern int nni_sock_ep_add(nni_sock *, nni_ep *); extern void nni_sock_ep_remove(nni_sock *, nni_ep *); diff --git a/src/core/transport.c b/src/core/transport.c index 38f88c4d..b48c7da6 100644 --- a/src/core/transport.c +++ b/src/core/transport.c @@ -38,7 +38,6 @@ nni_tran_register(const nni_tran *tran) { nni_transport *t; int rv; - size_t sz; // Its entirely possible that we are called before any sockets // are opened. Make sure we are initialized. This has to be diff --git a/src/core/url.c b/src/core/url.c index 3d8898bd..88a0cf0a 100644 --- a/src/core/url.c +++ b/src/core/url.c @@ -225,7 +225,7 @@ static struct { // clang-format on }; -static const char * +const char * nni_url_default_port(const char *scheme) { const char *s; @@ -255,7 +255,6 @@ nni_url_parse(nni_url **urlp, const char *raw) { nni_url * url; size_t len; - int outlen; const char *s; char c; int rv; @@ -480,4 +479,4 @@ nni_url_clone(nni_url **dstp, const nni_url *src) #undef URL_COPYSTR *dstp = dst; return (0); -}
\ No newline at end of file +} diff --git a/src/core/url.h b/src/core/url.h index 27aec445..b3407277 100644 --- a/src/core/url.h +++ b/src/core/url.h @@ -27,5 +27,6 @@ struct nni_url { extern int nni_url_parse(nni_url **, const char *path); extern void nni_url_free(nni_url *); extern int nni_url_clone(nni_url **, const nni_url *); +extern const char *nni_url_default_port(const char *); #endif // CORE_URL_H |
