Server 0.0.1
HTTP/REST server implementation

src/server/run.c File Reference

#include "server.h"
#include "logger.h"
#include "utils/signalHandling.h"
Include dependency graph for run.c:

Go to the source code of this file.

Functions

int serverPoll (Server)
int serverHandleAccept (Server, unsigned int)
void serverCloseConn (Server, unsigned int)
ssize_t serverRead (Server, unsigned int)
ssize_t serverWrite (Server, unsigned int)
void serverRun (Server this)

Detailed Description

Author:
Georg Hopp

Copyright © 2012 Georg Hopp

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.

Definition in file run.c.


Function Documentation

void serverCloseConn ( Server  ,
unsigned  int 
)

Definition at line 31 of file close_conn.c.

{
        int    fd = (this->fds)[i].fd;
        Stream st = (this->conns[fd]).stream;

        delete((this->conns)[fd].sock);
        delete((this->conns)[fd].worker);

        if (NULL != st && STREAM_SSL == st->type) {
                SSL_shutdown((st->handle).ssl);
                SSL_free((st->handle).ssl);
        }

        delete(st);

        memset(&(this->fds[i]), 0, sizeof(struct pollfd));
}
int serverHandleAccept ( Server  ,
unsigned  int 
)

Definition at line 36 of file handle_accept.c.

{
        char   remoteAddr[16] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
        Sock   acc = NULL;
        Stream st;

        if (this->nfds >= this->max_fds) {
                return -1;
        }

        acc = socketAccept((0 == i)? this->sock : this->sockSSL, &remoteAddr);

        if (-1 != acc->handle) {
        switch(i) {
                case 0:
                        // no SSL
                        st = new(Stream, STREAM_FD, acc->handle);
                        break;

                case 1:
                        // SSL
                        {
                                SSL * ssl = SSL_new(this->ctx);
                                SSL_set_fd(ssl, acc->handle);
                                SSL_accept(ssl);
                                st = new(Stream, STREAM_SSL, ssl);
                        }
                        break;

                default:
                        break;
        }

                // save the socket handle
                (this->conns)[acc->handle].sock   = acc; 

                // clone worker
                (this->conns)[acc->handle].worker = clone(this->worker);
                (this->conns)[acc->handle].stream = st;

                (this->fds)[this->nfds].fd        = acc->handle;
                (this->fds)[this->nfds].events    = POLLIN;
                this->nfds++;
        } else {
                delete(acc);

                switch(errno) {
                        case EAGAIN:
                                loggerLog(this->logger,
                                                LOGGER_DEBUG,
                                                "server accept blocks");
                                break;

                        default:
                                loggerLog(this->logger,
                                                LOGGER_DEBUG,
                                                "server accept error");
                                break;
                }
        }

        return (acc)? acc->handle : -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int serverPoll ( Server  )

put all closed fds to end of array in O(this->nfds)

Definition at line 34 of file poll.c.

                        {
        int events;

        struct pollfd * fda = &(this->fds[2]);
        struct pollfd * fdb = &(this->fds[this->nfds-1]);

        while (fda <= fdb) {
                while (0 == fdb->fd && fda <= fdb) {
                        fdb--;
                        this->nfds--;
                }

                while (0 != fda->fd && fda <= fdb) fda++;

                if (fda < fdb) {
                        memcpy(fda, fdb, sizeof(struct pollfd));
                        fdb--;
                        this->nfds--;
                }
        }

        /*
         * wait for handles to become ready
         */
        if (-1 == (events = poll(this->fds, this->nfds, -1))) {
                switch (errno) {
                        default:
                        case EBADF:
                        case EINVAL:
                        case ENOMEM:
                                doShutdown = 1;
                                // DROP THROUGH

                        case EINTR:
                                loggerLog(this->logger, LOGGER_CRIT,
                                                "poll systemcall failed: [%s] - service terminated",
                                                strerror(errno));
                }
        }

        return events;
}

Here is the call graph for this function:

Here is the caller graph for this function:

ssize_t serverRead ( Server  ,
unsigned  int 
)

normal close: this must be mapped to -2 within the underlying read call.

Todo:
make sure all pending writes will be done before close.

Definition at line 30 of file read.c.

{
        int     fd = (this->fds)[i].fd;
        ssize_t size;

        if (NULL == (this->conns)[fd].worker) {
                loggerLog(
                                this->logger,
                                LOGGER_INFO,
                                "initialization error: NULL reader");
                return -1;
        }

        switch ((size = streamReaderRead(
                                        (this->conns)[fd].worker,
                                        (this->conns)[fd].stream)))
        {
                case -2:
                        // DROP-THROUGH

                case -1: 
                        /*
                         * read failure / close connection
                         */
                        loggerLog(this->logger, LOGGER_INFO,
                                        "connection[%d] closed...%s",
                                        fd,
                                        inet_ntoa((((this->conns)[fd].sock)->addr).sin_addr));
                        serverCloseConn(this, i);
                        break;

                case 0:
                        break;

                default:
                        (this->fds)[i].events |= POLLOUT;
                        break;
        }

        return size;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void serverRun ( Server  this)

until error or signal

handle accept

handle accept SSL

handle reads

handle writes

Definition at line 35 of file run.c.

{
    loggerLog(this->logger, LOGGER_INFO, "service started");

    while (!doShutdown) 
    {
                int          events;
                unsigned int i;
                int          naccs = 10;

                events = serverPoll(this);
                if (doShutdown || 0 >= events) break;

                if (0 != ((this->fds)[0].revents & POLLIN)) {
                        events--;
                        while(-1 != serverHandleAccept(this, 0) && 0 < naccs) {
                                naccs--;
                        }
                }

                if (0 != ((this->fds)[1].revents & POLLIN)) {
                        events--;
                        while(-1 != serverHandleAccept(this, 1) && 0 < naccs) {
                                naccs--;
                        }
                }

                for (i=2; i < this->nfds; i++) {
                        int nreads = 10, nwrites = 10;

                        if (0 != ((this->fds)[i].revents & POLLIN) && 0 < nreads) {
                                events--;
                                nreads--;

                                serverRead(this, i);
                        }

                        if (0 != ((this->fds)[i].revents & POLLOUT) && 0 < nwrites) {
                                events--;
                                nwrites--;

                                serverWrite(this, i);
                        }

                        if (0 > events)
                                break; // no more events to handle
                }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

ssize_t serverWrite ( Server  ,
unsigned  int 
)

Definition at line 30 of file write.c.

{
        int     fd = (this->fds)[i].fd;
        ssize_t remaining;

        if (NULL == (this->conns)[fd].worker) {
                loggerLog(
                                this->logger,
                                LOGGER_INFO,
                                "initialization error: NULL worker");
                return -1;
        }

        remaining = streamWriterWrite(
                        (this->conns)[fd].worker,
                        (this->conns)[fd].stream);

        switch(remaining) {
                case -1:
                        serverCloseConn(this, i);
                        break;

                case 0:
                        (this->fds)[i].events &= ~POLLOUT;
                        break;

                default:
                        break;
        }

        return remaining;
}

Here is the call graph for this function:

Here is the caller graph for this function:

 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines