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; }
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); }