I am new to networking-discuss. I searched for an earlier discussion of
the following, but didn't find one.
Does anyone have a cookbook to follow for how to write a
socket-connect-with-timeout function, for kernel sockets, using the
ksock_cb_connected callback? The enclosed routines seem to be working.
I just want to double check that I am not out on the bleeding edge.
Peter Cudhea
Mutex idm_so_timed_socket_mutex is initiatialized at _init time.
static void
idm_so_socket_set_nonblock(struct sonode *node)
{
(void) VOP_SETFL(node->so_vnode, node->so_flag,
(node->so_state | FNONBLOCK), CRED(), NULL);
}
static void
idm_so_socket_set_block(struct sonode *node)
{
(void) VOP_SETFL(node->so_vnode, node->so_flag,
(node->so_state & (~FNONBLOCK)), CRED(), NULL);
}
/* ARGSUSED */
void *
idm_so_timed_socket_connect_cb(ksocket_t ks,
ksocket_callback_event_t ev, void *arg, uintptr_t info)
{
kcondvar_t *cv = (kcondvar_t *) arg;
ASSERT(cv != NULL);
ASSERT(ev == KSOCKET_EV_CONNECTED || ev == KSOCKET_EV_CONNECTFAILED);
mutex_enter(&idm_so_timed_socket_mutex);
cv_signal(cv);
mutex_exit(&idm_so_timed_socket_mutex);
return (NULL);
}
int
idm_so_timed_socket_connect(ksocket_t ks,
struct sockaddr_storage *sa, int sa_sz, int login_max_usec)
{
clock_t conn_login_max, lbolt;
struct sonode *node;
int rc;
ksocket_callbacks_t ks_cb;
kcondvar_t ks_cv;
node = (struct sonode *)ks;
conn_login_max = ddi_get_lbolt() + drv_usectohz(login_max_usec);
/* Set to non-block socket mode, with callback on connect */
bzero(&ks_cb, sizeof (ks_cb));
ks_cb.ksock_cb_flags = KSOCKET_CB_CONNECTED | KSOCKET_CB_CONNECTFAILED;
ks_cb.ksock_cb_connected =
(ksocket_callback_t) idm_so_timed_socket_connect_cb;
cv_init(&ks_cv, NULL, CV_DEFAULT, NULL);
(void) ksocket_setcallbacks(ks, &ks_cb, (void *)&ks_cv, CRED());
idm_so_socket_set_nonblock(node);
mutex_enter(&idm_so_timed_socket_mutex);
for (;;) {
rc = ksocket_connect(ks, (struct sockaddr *)sa, sa_sz, CRED());
if (rc == 0 || rc == EISCONN) {
/* socket success or already success */
rc = 0;
break;
}
if ((rc != EINPROGRESS) && (rc != EALREADY)) {
break;
}
lbolt = ddi_get_lbolt();
if (lbolt > conn_login_max) {
/*
* Connection retry timeout,
* failed connect to target.
*/
rc = ETIMEDOUT;
break;
}
/* TCP connect still in progress. Sleep until callback. */
(void) cv_timedwait(&ks_cv, &idm_so_timed_socket_mutex,
conn_login_max);
}
mutex_exit(&idm_so_timed_socket_mutex);
/* resume blocking mode */
ksocket_setcallbacks(ks, NULL, NULL, CRED());
idm_so_socket_set_block(node);
cv_destroy(&ks_cv);
return (rc);
}
_______________________________________________
networking-discuss mailing list
[email protected]