void server::
    start_async (
    )
    {
        auto_mutex lock(running_mutex);
        if (running)
            return;

        // Any exceptions likely to be thrown by the server are going to be
        // thrown when trying to bind the port.  So calling this here rather
        // than in the thread we are about to make will cause start_async()
        // to report errors back to the user in a very straight forward way.
        open_listening_socket();

        async_start_thread.reset(new thread_function(make_mfp(*this,&server::start_async_helper)));
    }
Exemple #2
0
int rst_sockets(struct cpt_context *ctx)
{
    int err;
    loff_t sec = ctx->sections[CPT_SECT_SOCKET];
    loff_t endsec;
    cpt_object_t *obj;
    struct cpt_section_hdr h;

    if (sec == CPT_NULL)
        return 0;

    err = ctx->pread(&h, sizeof(h), ctx, sec);
    if (err) {
        eprintk_ctx("rst_sockets: ctx->pread: %d\n", err);
        return err;
    }
    if (h.cpt_section != CPT_SECT_SOCKET || h.cpt_hdrlen < sizeof(h)) {
        eprintk_ctx("rst_sockets: hdr err\n");
        return -EINVAL;
    }

    /* The first pass: we create socket index and open listening sockets. */
    endsec = sec + h.cpt_next;
    sec += h.cpt_hdrlen;
    while (sec < endsec) {
        struct cpt_sock_image *sbuf = cpt_get_buf(ctx);
        err = rst_get_object(CPT_OBJ_SOCKET, sec, sbuf, ctx);
        if (err) {
            eprintk_ctx("rst_sockets: rst_get_object: %d\n", err);
            cpt_release_buf(ctx);
            return err;
        }
        if (sbuf->cpt_state == TCP_LISTEN) {
            err = open_listening_socket(sec, sbuf, ctx);
            cpt_release_buf(ctx);
            if (err) {
                eprintk_ctx("rst_sockets: open_listening_socket: %d\n", err);
                return err;
            }
        } else {
            cpt_release_buf(ctx);
            obj = alloc_cpt_object(GFP_KERNEL, ctx);
            if (obj == NULL)
                return -ENOMEM;
            cpt_obj_setindex(obj, sbuf->cpt_index, ctx);
            cpt_obj_setpos(obj, sec, ctx);
            obj->o_ppos  = sbuf->cpt_file;
            intern_cpt_object(CPT_OBJ_SOCKET, obj, ctx);
        }
        sec += sbuf->cpt_next;
    }

    /* Pass 2: really restore sockets */
    for_each_object(obj, CPT_OBJ_SOCKET) {
        struct cpt_sock_image *sbuf;
        if (obj->o_obj != NULL)
            continue;
        sbuf = cpt_get_buf(ctx);
        err = rst_get_object(CPT_OBJ_SOCKET, obj->o_pos, sbuf, ctx);
        if (err) {
            eprintk_ctx("rst_sockets: rst_get_object: %d\n", err);
            cpt_release_buf(ctx);
            return err;
        }
        if (sbuf->cpt_state == TCP_LISTEN) BUG();
        err = open_socket(obj, sbuf, ctx);
        cpt_release_buf(ctx);
        if (err) {
            eprintk_ctx("rst_sockets: open_socket: %d\n", err);
            return err;
        }
    }

    return 0;
}
    void server::
    start_accepting_connections (
    )
    {
        open_listening_socket();

        // determine the listening port
        bool port_assigned = false;
        listening_port_mutex.lock();
        if (listening_port == 0)
        {
            port_assigned = true;
            listening_port = sock->get_listening_port();
        }
        listening_port_mutex.unlock();
        if (port_assigned)
            on_listening_port_assigned();
        


        int status = 0;

        connection* client;
        bool exit = false;
        while ( true )
        {


            // accept the next connection
            status = sock->accept(client,1000);


            // if there was an error then quit the loop
            if (status == OTHER_ERROR)
            {
                break;
            }

            shutting_down_mutex.lock();
            // if we are shutting down then signal that we should quit the loop
            exit = shutting_down;
            shutting_down_mutex.unlock();  


            // if we should be shutting down 
            if (exit)
            {
                // if a connection was opened then close it
                if (status == 0)
                    delete client;
                break;
            }



            // if the accept timed out
            if (status == TIMEOUT)
            {
                continue;       
            }





            // add this new connection to cons
            cons_mutex.lock();
            connection* client_temp = client;
            try{cons.add(client_temp);}
            catch(...)
            { 
                sock.reset();
                delete client;
                cons_mutex.unlock();

                // signal that we are not running start() anymore
                running_mutex.lock();
                running = false;
                running_signaler.broadcast();
                running_mutex.unlock();               
                

                clear(); 
                throw;
            }
            cons_mutex.unlock();


            // make a param structure
            param* temp = 0;
            try{
            temp = new param (
                            *this,
                            *client,
                            get_graceful_close_timeout() 
                            );
            } catch (...) 
            {
                sock.reset();
                delete client;
                running_mutex.lock();
                running = false;
                running_signaler.broadcast();
                running_mutex.unlock();
                clear(); 
                throw;
            }


            // if create_new_thread failed
            if (!create_new_thread(service_connection,temp))
            {
                delete temp;
                // close the listening socket
                sock.reset();

                // close the new connection and remove it from cons
                cons_mutex.lock();
                connection* ctemp;
                if (cons.is_member(client))
                {
                    cons.remove(client,ctemp);
                }
                delete client;
                cons_mutex.unlock();


                // signal that the listener has closed
                running_mutex.lock();
                running = false;
                running_signaler.broadcast();
                running_mutex.unlock();

                // make sure the object is cleared
                clear();

                // throw the exception
                throw dlib::thread_error(
                    ECREATE_THREAD,
                    "error occurred in server::start()\nunable to start thread"
                    );    
            }
            // if we made the new thread then update thread_count
            else
            {
                // increment the thread count
                thread_count_mutex.lock();
                ++thread_count;
                if (thread_count == 0)
                    thread_count_zero.broadcast();
                thread_count_mutex.unlock();
            }


            

            // check if we have hit the maximum allowed number of connections
            max_connections_mutex.lock();
            // if max_connections is zero or the loop is ending then skip this
            if (max_connections != 0)
            {
                // wait for thread_count to be less than max_connections
                thread_count_mutex.lock();
                while (thread_count >= max_connections)
                {
                    max_connections_mutex.unlock();
                    thread_count_signaler.wait();
                    max_connections_mutex.lock();     

                    // if we are shutting down the quit the loop
                    shutting_down_mutex.lock();
                    exit = shutting_down;
                    shutting_down_mutex.unlock();
                    if (exit)
                        break;
                }
                thread_count_mutex.unlock();
            }
            max_connections_mutex.unlock();

            if (exit)
            {
                break;
            }
        } //while ( true )


        // close the socket
        sock.reset();

        // signal that the listener has closed
        running_mutex.lock();
        running = false;
        running_signaler.broadcast();
        running_mutex.unlock();

        // if there was an error with accept then throw an exception
        if (status == OTHER_ERROR)
        {
            // make sure the object is cleared
            clear();

            // throw the exception
            throw dlib::socket_error(
             "error occurred in server::start()\nlistening socket returned error"
                );            
        }
    }