⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 response.c

📁 网络流量采集及分析软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/*! \file   response.c  Based on webfs Copyright (C) 1999-2001  Gerd Knorr  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 2 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 with  the Debian GNU/Linux distribution in file /usr/share/common-licenses/GPL;  if not, write to the Free Software Foundation, Inc., 59 Temple Place,  Suite 330, Boston, MA  02111-1307  USA  Description:  http response handling  $Id: response.c,v 1.3 2005/06/03 04:43:33 s_zander Exp $*/#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 <netinet/tcp.h>#include "httpd.h"/* ---------------------------------------------------------------------- *//* os-specific sendfile() wrapper                                         *//* * int xsendfile(out,in,offset,bytes) * *	out    - outgoing filedescriptor (i.e. the socket) *	in     - incoming filedescriptor (i.e. the file to send out) *	offset - file offset (where to start) *      bytes  - number of bytes to send * * return value *	on error:   -1 and errno set. *	on success: the number of successfully written bytes (which might *		    be smaller than bytes, we are doing nonblocking I/O). *	extra hint: much like write(2) works. * */#if defined(__linux__) && !defined(NO_SENDFILE)# include <sys/sendfile.h>static int xsendfile(int out, int in, off_t offset, size_t bytes){    return sendfile(out, in, &offset, bytes);}#elif defined(__FreeBSD__) && !defined(NO_SENDFILE)static int xsendfile(int out, int in, off_t offset, size_t bytes){    off_t nbytes = 0;    if (sendfile(in, out, offset, bytes, NULL, &nbytes, 0) == -1) {        /* Why the heck FreeBSD returns an /error/ if it has done a partial           write?  With non-blocking I/O this absolutely normal behavoir and           no error at all.  Stupid. */        if (errno == EAGAIN && nbytes > 0) {            return nbytes;        }        return -1;    }    return nbytes;}#else# warning using slow sendfile() emulation./* Poor man's sendfile() implementation. Performance sucks, but it works. */#define BUFSIZE 16384static int xsendfile(int out, int in, off_t offset, size_t bytes){    char buf[BUFSIZE];    ssize_t nread;    ssize_t nsent, nsent_total;    if (lseek(in, offset, SEEK_SET) == -1) {#ifdef DEBUG	    perror("lseek");#endif        return -1;    }    nsent = nsent_total = 0;    for (;bytes > 0;) {        /* read a block */        nread = read(in, buf, (bytes < BUFSIZE) ? bytes : BUFSIZE);        if (nread == -1) {#ifdef DEBUG            perror("read");#endif            return nsent_total ? nsent_total : -1;        }        if (nread == 0) {            break;        }        /* write it out */        nsent = write(out, buf, nread);        if (nsent == -1) {            return nsent_total ? nsent_total : -1;        }        nsent_total += nsent;        if (nsent < nread) {            /* that was a partial write only.  Queue full.  Bailout here,               the next write would return EAGAIN anyway... */            break;        }            bytes -= nread;    }    return nsent_total;}#endif/* ---------------------------------------------------------------------- */#ifdef USE_SSLstatic inline int wrap_xsendfile(struct REQUEST *req, off_t off, size_t bytes){    if (with_ssl) {        return ssl_blk_write(req,off,bytes);    } else {        return xsendfile(req->fd, req->bfd, off, bytes);    }}static inline int wrap_write(struct REQUEST *req, void *buf, size_t bytes){    if (with_ssl) {        return ssl_write(req,buf,bytes);    } else {        return write(req->fd, buf, bytes);    }}#elsestatic inline int wrap_xsendfile(struct REQUEST *req, off_t off, size_t bytes){    return xsendfile(req->fd,req->bfd,off,bytes);}static inline int wrap_write(struct REQUEST *req, void *buf, size_t bytes){    return write(req->fd,buf,bytes);}#endif/* ---------------------------------------------------------------------- */static struct HTTP_STATUS {    int   status;    char *head;    char *body;} http[] = {    { 200, "200 OK",                       NULL },    { 206, "206 Partial Content",          NULL },    { 304, "304 Not Modified",             NULL },    { 400, "400 Bad Request",              "*PLONK*\n" },    { 401, "401 Authentication required",  "Authentication required\n" },    { 403, "403 Forbidden",                "Access denied\n" },    { 404, "404 Not Found",                "File or directory not found\n" },    { 408, "408 Request Timeout",          "Request Timeout\n" },    { 412, "412 Precondition failed.",     "Precondition failed\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"		\	"Accept-Ranges: bytes\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=\"NetMate\"\r\n");    }    req->lres += strftime(req->hres+req->lres,80,                          "Date: " RFCTIME "\r\n\r\n",                          gmtime(&now));    req->state = STATE_WRITE_HEADER;#ifdef DEBUG	fprintf(stderr,"%03d/%d: error: %d, connection=%s\n",            req->fd, req->state, status, req->keep_alive ? "Keep-Alive" : "Close");#endif}void mkredirect(struct REQUEST *req, int tcp_port){    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,quote(req->path,9999),                        req->lbody);    req->lres += strftime(req->hres+req->lres,80,                          "Date: " RFCTIME "\r\n\r\n",                          gmtime(&now));    req->state = STATE_WRITE_HEADER;#ifdef DEBUG	fprintf(stderr,"%03d/%d: 302 redirect: %s, connection=%s\n",            req->fd, req->state, req->path, req->keep_alive ? "Keep-Alive" : "Close");#endif}static int mkmulti(struct REQUEST *req, int i){    req->r_hlen[i] = sprintf(req->r_head+i*BR_HEADER,                             "\r\n--" BOUNDARY "\r\n"                             "Content-type: %s\r\n"#if (SIZEOF_OFF_T == 4)                             "Content-range: bytes %ld-%ld/%ld\r\n"#else                             "Content-range: bytes %lld-%lld/%lld\r\n"#endif                             "\r\n",                             (unsigned long)now, req->mime,                             req->r_start[i],req->r_end[i]-1,req->bst.st_size);#ifdef DEBUG#if (SIZEOF_OFF_T == 4)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -