Logo Search packages:      
Sourcecode: xawtv version File versions  Download package

response.c

#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <syslog.h>
#include <time.h>

#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include "httpd.h"

/* ---------------------------------------------------------------------- */

static struct HTTP_STATUS {
    int   status;
    char *head;
    char *body;
} http[] = {
    { 200, "200 OK",                       NULL },
    { 400, "400 Bad Request",              "*PLONK*\n" },
    { 404, "404 Not Found",       "videotext page not found in cache\n" },
    { 408, "408 Request Timeout",          "Request Timeout\n" },
    { 500, "500 Internal Server Error",    "Sorry folks\n" },
    { 501, "501 Not Implemented",          "Sorry folks\n" },
    {   0, NULL,                        NULL }
};

/* ---------------------------------------------------------------------- */

#define RESPONSE_START              \
      "HTTP/1.1 %s\r\n"       \
      "Server: %s\r\n"        \
      "Connection: %s\r\n"
#define RFCTIME                     \
      "%a, %d %b %Y %H:%M:%S GMT"
#define BOUNDARY              \
      "XXX_CUT_HERE_%ld_XXX"

void
mkerror(struct REQUEST *req, int status, int ka)
{
    int i;
    for (i = 0; http[i].status != 0; i++)
      if (http[i].status == status)
          break;
    req->status = status;
    req->body   = http[i].body;
    req->lbody  = strlen(req->body);
    if (!ka)
      req->keep_alive = 0;
    req->lres = sprintf(req->hres,
                  RESPONSE_START
                  "Content-Type: text/plain\r\n"
                  "Content-Length: %d\r\n",
                  http[i].head,server_name,
                  req->keep_alive ? "Keep-Alive" : "Close",
                  req->lbody);
    if (401 == status)
      req->lres += sprintf(req->hres+req->lres,
                       "WWW-Authenticate: Basic, realm=\"webfs\"\r\n");
    req->lres += strftime(req->hres+req->lres,80,
                    "Date: " RFCTIME "\r\n\r\n",
                    gmtime(&now));
    req->state = STATE_WRITE_HEADER;
    if (debug)
      fprintf(stderr,"%03d: error: %d, connection=%s\n",
            req->fd, status, req->keep_alive ? "Keep-Alive" : "Close");
}

void
mkredirect(struct REQUEST *req)
{
    req->status = 302;
    req->body   = req->path;
    req->lbody  = strlen(req->body);
    req->lres = sprintf(req->hres,
                  RESPONSE_START
                  "Location: http://%s:%d%s\r\n"
                  "Content-Type: text/plain\r\n"
                  "Content-Length: %d\r\n",
                  "302 Redirect",server_name,
                  req->keep_alive ? "Keep-Alive" : "Close",
                  req->hostname,tcp_port,req->path,
                  req->lbody);
    req->lres += strftime(req->hres+req->lres,80,
                    "Date: " RFCTIME "\r\n\r\n",
                    gmtime(&now));
    req->state = STATE_WRITE_HEADER;
    if (debug)
      fprintf(stderr,"%03d: 302 redirect: %s, connection=%s\n",
            req->fd, req->path, req->keep_alive ? "Keep-Alive" : "Close");
}

void
mkheader(struct REQUEST *req, int status, time_t mtime)
{
    int    i;
    for (i = 0; http[i].status != 0; i++)
      if (http[i].status == status)
          break;
    req->status = status;
    req->lres = sprintf(req->hres,
                  RESPONSE_START,
                  http[i].head,server_name,
                  req->keep_alive ? "Keep-Alive" : "Close");
    req->lres += sprintf(req->hres+req->lres,
                   "Content-Type: %s\r\n"
                   "Content-Length: %d\r\n",
                   req->mime,
                   req->lbody);
    if (mtime != -1)
        req->lres += strftime(req->hres+req->lres,80,
                              "Last-Modified: " RFCTIME "\r\n",
                              gmtime(&mtime));
    req->lres += strftime(req->hres+req->lres,80,
                    "Date: " RFCTIME "\r\n\r\n",
                    gmtime(&now));
    req->state = STATE_WRITE_HEADER;
    if (debug)
      fprintf(stderr,"%03d: %d, connection=%s\n",
            req->fd, status, req->keep_alive ? "Keep-Alive" : "Close");
}

/* ---------------------------------------------------------------------- */

void write_request(struct REQUEST *req)
{
    int rc;

    for (;;) {
      switch (req->state) {
      case STATE_WRITE_HEADER:
          rc = write(req->fd,req->hres + req->written,
                   req->lres - req->written);
          switch (rc) {
          case -1:
            if (errno == EAGAIN)
                return;
            if (errno == EINTR)
                continue;
            xperror(LOG_INFO,"write",req->peerhost);
            /* fall through */
          case 0:
            req->state = STATE_CLOSE;
            return;
          default:
            req->written += rc;
            req->bc += rc;
            if (req->written != req->lres)
                return;
          }
          req->written = 0;
          if (req->head_only) {
            req->state = STATE_FINISHED;
            return;
          } else {
            req->state = STATE_WRITE_BODY;
          }
          break;
      case STATE_WRITE_BODY:
          rc = write(req->fd,req->body + req->written,
                   req->lbody - req->written);
          switch (rc) {
          case -1:
            if (errno == EAGAIN)
                return;
            if (errno == EINTR)
                continue;
            xperror(LOG_INFO,"write",req->peerhost);
            /* fall through */
          case 0:
            req->state = STATE_CLOSE;
            return;
          default:
            req->written += rc;
            req->bc += rc;
            if (req->written != req->lbody)
                return;
          }
          req->state = STATE_FINISHED;
          return;
      } /* switch(state) */
    } /* for (;;) */
}

Generated by  Doxygen 1.6.0   Back to index