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]

Reply via email to