示例#1
0
int webserv(int sockfd) {
	char buf[MAXLINE];
	char page[MAXLINE];
	struct user_request request;

	if (read(sockfd, buf, MAXLINE) <= 0) {// 클라이언트 요청 읽어서 buf 저장
		perror("read");
		return ERROR;
	}

	printf("%s", buf);
	protocol_parser(buf, &request); // 클라이언트 요청 분석해서request 저장

	if (!strcmp(request.method, "GET")) { // GET 요청이면
		sprintf(page, "%s%s", root, request.page);
		if (access(page, R_OK)) { // 파일을 읽을 수 없으면
			sendpage(sockfd, NULL, request.http_ver, "404 Not Found");
		} else { // 파일 있으면 보내줌
			sendpage(sockfd, page, request.http_ver, "200 OK");
		}
	} else { // GET 아니면 500 error
		sendpage(sockfd, NULL, request.http_ver, "500 Internal Server Error");
	}
	return 0;
}
示例#2
0
static inline int xs_send_head(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, unsigned int len)
{
    struct kvec iov = {
        .iov_base	= xdr->head[0].iov_base + base,
        .iov_len	= len - base,
    };
    struct msghdr msg = {
        .msg_name	= addr,
        .msg_namelen	= addrlen,
        .msg_flags	= XS_SENDMSG_FLAGS,
    };

    if (xdr->len > len)
        msg.msg_flags |= MSG_MORE;

    if (likely(iov.iov_len))
        return kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
    return kernel_sendmsg(sock, &msg, NULL, 0, 0);
}

static int xs_send_tail(struct socket *sock, struct xdr_buf *xdr, unsigned int base, unsigned int len)
{
    struct kvec iov = {
        .iov_base	= xdr->tail[0].iov_base + base,
        .iov_len	= len - base,
    };
    struct msghdr msg = {
        .msg_flags	= XS_SENDMSG_FLAGS,
    };

    return kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len);
}

/**
 * xs_sendpages - write pages directly to a socket
 * @sock: socket to send on
 * @addr: UDP only -- address of destination
 * @addrlen: UDP only -- length of destination address
 * @xdr: buffer containing this request
 * @base: starting position in the buffer
 *
 */
static inline int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base)
{
    struct page **ppage = xdr->pages;
    unsigned int len, pglen = xdr->page_len;
    int err, ret = 0;
    ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);

    if (unlikely(!sock))
        return -ENOTCONN;

    clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);

    len = xdr->head[0].iov_len;
    if (base < len || (addr != NULL && base == 0)) {
        err = xs_send_head(sock, addr, addrlen, xdr, base, len);
        if (ret == 0)
            ret = err;
        else if (err > 0)
            ret += err;
        if (err != (len - base))
            goto out;
        base = 0;
    } else
        base -= len;

    if (unlikely(pglen == 0))
        goto copy_tail;
    if (unlikely(base >= pglen)) {
        base -= pglen;
        goto copy_tail;
    }
    if (base || xdr->page_base) {
        pglen -= base;
        base += xdr->page_base;
        ppage += base >> PAGE_CACHE_SHIFT;
        base &= ~PAGE_CACHE_MASK;
    }

    sendpage = kernel_sendpage;
    do {
        int flags = XS_SENDMSG_FLAGS;

        len = PAGE_CACHE_SIZE;
        if (base)
            len -= base;
        if (pglen < len)
            len = pglen;

        if (pglen != len || xdr->tail[0].iov_len != 0)
            flags |= MSG_MORE;

        /* Hmm... We might be dealing with highmem pages */
        if (PageHighMem(*ppage))
            sendpage = sock_no_sendpage;
        err = sendpage(sock, *ppage, base, len, flags);
        if (ret == 0)
            ret = err;
        else if (err > 0)
            ret += err;
        if (err != len)
            goto out;
        base = 0;
        ppage++;
    } while ((pglen -= len) != 0);
copy_tail:
    len = xdr->tail[0].iov_len;
    if (base < len) {
        err = xs_send_tail(sock, xdr, base, len);
        if (ret == 0)
            ret = err;
        else if (err > 0)
            ret += err;
    }
out:
    return ret;
}

/**
 * xs_nospace - place task on wait queue if transmit was incomplete
 * @task: task to put to sleep
 *
 */
static void xs_nospace(struct rpc_task *task)
{
    struct rpc_rqst *req = task->tk_rqstp;
    struct rpc_xprt *xprt = req->rq_xprt;

    dprintk("RPC: %4d xmit incomplete (%u left of %u)\n",
            task->tk_pid, req->rq_slen - req->rq_bytes_sent,
            req->rq_slen);

    if (test_bit(SOCK_ASYNC_NOSPACE, &xprt->sock->flags)) {
        /* Protect against races with write_space */
        spin_lock_bh(&xprt->transport_lock);

        /* Don't race with disconnect */
        if (!xprt_connected(xprt))
            task->tk_status = -ENOTCONN;
        else if (test_bit(SOCK_NOSPACE, &xprt->sock->flags))
            xprt_wait_for_buffer_space(task);

        spin_unlock_bh(&xprt->transport_lock);
    } else
        /* Keep holding the socket if it is blocked */
        rpc_delay(task, HZ>>4);
}

/**
 * xs_udp_send_request - write an RPC request to a UDP socket
 * @task: address of RPC task that manages the state of an RPC request
 *
 * Return values:
 *        0:	The request has been sent
 *   EAGAIN:	The socket was blocked, please call again later to
 *		complete the request
 * ENOTCONN:	Caller needs to invoke connect logic then call again
 *    other:	Some other error occured, the request was not sent
 */
static int xs_udp_send_request(struct rpc_task *task)
{
    struct rpc_rqst *req = task->tk_rqstp;
    struct rpc_xprt *xprt = req->rq_xprt;
    struct xdr_buf *xdr = &req->rq_snd_buf;
    int status;

    xs_pktdump("packet data:",
               req->rq_svec->iov_base,
               req->rq_svec->iov_len);

    req->rq_xtime = jiffies;
    status = xs_sendpages(xprt->sock, (struct sockaddr *) &xprt->addr,
                          sizeof(xprt->addr), xdr, req->rq_bytes_sent);

    dprintk("RPC:      xs_udp_send_request(%u) = %d\n",
            xdr->len - req->rq_bytes_sent, status);

    if (likely(status >= (int) req->rq_slen))
        return 0;

    /* Still some bytes left; set up for a retry later. */
    if (status > 0)
        status = -EAGAIN;

    switch (status) {
    case -ENETUNREACH:
    case -EPIPE:
    case -ECONNREFUSED:
        /* When the server has died, an ICMP port unreachable message
         * prompts ECONNREFUSED. */
        break;
    case -EAGAIN:
        xs_nospace(task);
        break;
    default:
        dprintk("RPC:      sendmsg returned unrecognized error %d\n",
                -status);
        break;
    }

    return status;
}

static inline void xs_encode_tcp_record_marker(struct xdr_buf *buf)
{
    u32 reclen = buf->len - sizeof(rpc_fraghdr);
    rpc_fraghdr *base = buf->head[0].iov_base;
    *base = htonl(RPC_LAST_STREAM_FRAGMENT | reclen);
}