ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n) { size_t nleft = n; ssize_t nread; char *bufp = usrbuf; while(nleft > 0) { if ((nread = rio_readn(rp->rio_fd, bufp, nleft)) < 0) { if(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) { //线程不安全 nread = 0; } else { return -1; } } else if(nread == 0) break; nleft -= nread; bufp += nread; } return (n-nleft); }
/* $begin serve_static */ void serve_static(int fd, char *filename, int filesize) { int srcfd; char *srcp, filetype[MAXLINE], buf[MAXBUF]; int n; srcp = malloc(filesize); /* Send response headers to client */ get_filetype(filename, filetype); //line:netp:servestatic:getfiletype sprintf(buf, "HTTP/1.0 200 OK\r\n"); //line:netp:servestatic:beginserve sprintf(buf, "%sServer: Tiny Web Server\r\n", buf); sprintf(buf, "%sContent-length: %d\r\n", buf, filesize); sprintf(buf, "%sContent-type: %s\r\n\r\n", buf, filetype); Rio_writen(fd, buf, strlen(buf)); //line:netp:servestatic:endserve /* Send response body to client */ srcfd = Open(filename, O_RDONLY, 0); //line:netp:servestatic:open //srcp = Mmap(0, filesize, PROT_READ, MAP_PRIVATE, srcfd, 0);//line:netp:servestatic:mmap while ((n = rio_readn(srcfd, srcp, filesize + 1)) != 0) { Rio_writen(fd, srcp, filesize); } Close(srcfd); //line:netp:servestatic:close free(srcp); // Rio_writen(fd, srcp, filesize); //line:netp:servestatic:write // Munmap(srcp, filesize); //line:netp:servestatic:munmap }
/********************************** * * Wrappers for robust I/O routines * **********************************/ ssize_t Rio_readn(int fd, void *ptr, size_t nbytes) { ssize_t n; if ((n = rio_readn(fd, ptr, nbytes)) < 0) unix_error("Rio_readn error"); return n; }
ssize_t Rio_readn(int fd, void *userbuf, size_t n) { ssize_t rt; rt = rio_readn(fd, userbuf, n); if (rt == -1) unix_error("Rio_readn error"); return rt; }
ssize_t Rio_readn_s(int fd, void *ptr, size_t nbytes){ ssize_t n; if ((n = rio_readn(fd, ptr, nbytes)) < 0){ printf("Rio_readn error\n"); n = 0; } return n; }
/********************************** * Wrappers for robust I/O routines **********************************/ ssize_t Rio_readn(int fd, void *ptr, size_t nbytes) { ssize_t n; if ((n = rio_readn(fd, ptr, nbytes)) < 0) { if (errno != ECONNRESET) unix_error("Rio_readn error"); } return n; }
int main() { int n; rio_t rio; char buf[MAXLINE]; rio_readinitb(&rio, STDIN_FILENO); whle((n= rio_readn(&rio, buf, MAXBUF)) != 0) Rio_writen(STDOUT_FILENO, buf, MAXBUF); return 0; }
ssize_t Rio_readn(int fd, void *ptr, size_t nbytes) { ssize_t n; if ((n = rio_readn(fd, ptr, nbytes)) < 0) { if (errno != EPIPE) unix_error("Rio_readn error"); else { // printf("Rio_readn: socket has closed with EPIPE\n"); return -1; } } return n; }
bool page::read_full_page(int fd) { /* create an aligned array of bytes we can read into */ void* aligned_base; guard<char> ptr = (char*)aligned_alloc(page_size(), 512, &aligned_base); assert(ptr != NULL); /* read bytes over 'this' */ /* read system call may return short counts */ ssize_t size_read = rio_readn(fd, aligned_base, page_size()); /* check for error */ if (size_read == -1) THROW2(FileException, "::read failed %s", strerror(errno)); /* check for end of file */ if (size_read == 0) return false; /* rio_readn ensures we read the proper number of bytes */ /* save page attributes that we'll be overwriting */ page_pool* pool = _pool; memcpy(this, aligned_base, size_read); _pool = pool; /* more error checking */ if ( (page_size() != (size_t)size_read) ) { /* The page we read does not have the same size as the page object we overwrote. Luckily, we used the object size when reading, so we didn't overflow our internal buffer. */ TRACE(TRACE_ALWAYS, "Read %zd byte-page with internal page size of %zd bytes. " "Sizes should all match.\n", size_read, page_size()); THROW1(FileException, "::read read wrong size page"); } return true; }
char* networkClient::run(const std::string& wholeMessage) { std::string response; if(!isCreated()) createSocket(); connectSocket(); //Send this command to the network server char *buffer; buffer = new char[8192]; n = write(sockfd,wholeMessage.c_str(),wholeMessage.length()); fprintf(stdout,"Message wrote\n"); if (n < 0) fprintf(stderr,"ERROR writing to socket"); n = rio_readn(sockfd,buffer,8191); fprintf(stdout,"Message recv\n"); if (n < 0) fprintf(stderr,"ERROR reading from socket"); return(buffer); }
ssize_t rio_readline(int fd, void *usrbuf, size_t maxlen) { int n, rc; char c, *buf = usrbuf; for (n = 1; n < maxlen; n++) if ((rc = rio_readn(fd, &c, 1)) == 1) { *buf++ = c; if (c == '\n') break; } else if (rc == 0) { if (n == 1) return 0; else break; } else { return -1; } *buf = 0; return n; }
/* Wrapper for read (unbuffered) */ ssize_t Rio_readn(int fd, void *ptr, size_t nbytes) { ssize_t n; n = rio_readn(fd, ptr, nbytes); return n; }
/* Analyze the request from browser and decide whether retrieve from * cache or connect to the server*/ void* request (void* data){ pthread_detach(pthread_self()); Signal(SIGPIPE,SIG_IGN); signal(SIGPIPE,SIG_IGN); int serverfd=*(int*)data; int clientfd; char headerBuff[MAXHEADERSIZE],Buffer[MAXBUFFERSIZE]; char hostname[300],uriname[MAXHEADERSIZE],urlname[MAXHEADERSIZE]; char* cache_buff; int getbyte,error; int cachehit = 0; int cache_size = 0; free(data); rio_t serverrio_t; rio_readinitb(&serverrio_t,serverfd); rio_readlineb(&serverrio_t,headerBuff,sizeof(headerBuff)); if (takeHostUriUrl(headerBuff,hostname,uriname,urlname) ==0){ perror("Get Host Uri Url error\n"); close(serverfd); pthread_exit(NULL); } /* Try to get cached data, must check no thread writing the cache, * * and use FILO architecture to lock when there threads reading cache*/ P(&mutex); readcnt++; if(readcnt == 1) P(&w); V(&mutex); if( Get_cachedata(urlname,serverfd) > 0){ cachehit = 1; } P(&mutex); readcnt--; if(readcnt == 0) V(&w); V(&mutex); if(cachehit){ printf("Cache Hit!!!!\n"); close(serverfd); pthread_exit(NULL); } if( (clientfd=socket(AF_INET,SOCK_STREAM,0))<0){ perror("socket"); close(serverfd); pthread_exit(NULL); } /*get server's address info*/ struct addrinfo *hostinfo; if( (error=getaddrinfo(hostname,"http",NULL,&hostinfo)) >0){ perror("hostinfo"); close(serverfd); close(clientfd); pthread_exit(NULL); } /* connect to the server*/ if( (connect(clientfd,hostinfo->ai_addr,hostinfo->ai_addrlen))<0){ perror("connect"); close(serverfd); close(clientfd); return NULL; } cache_buff = (char*) malloc(MAX_OBJECT_SIZE*sizeof(char)); cache_size = 0; /* Send the request to the server */ SendRequest(clientfd,serverrio_t,hostname,uriname); /*read the information from web server and send it to browser*/ while(1){ getbyte = rio_readn(clientfd,Buffer,sizeof(Buffer)); if(getbyte <= 0 ) break; if(cache_size + getbyte < MAX_OBJECT_SIZE){ memcpy(cache_buff + cache_size,Buffer,getbyte); } cache_size += getbyte; rio_writen(serverfd,Buffer,getbyte); } /* if size fit in cache, write into cache, else free the content*/ if(cache_size < MAX_OBJECT_SIZE){ char* new_cache_buff = realloc(cache_buff,cache_size); free(cache_buff); if(new_cache_buff == NULL){ perror("Realloc fail\n"); close(clientfd); close(serverfd); pthread_exit(NULL); } P(&w); char *saveurlname = (char*)malloc(strlen(urlname)*sizeof(char)); memcpy(saveurlname,urlname,strlen(urlname)); Create_cache(saveurlname,new_cache_buff,cache_size); V(&w); } else{ free(cache_buff); } close(clientfd); close(serverfd); pthread_exit(NULL); }
void* HttpRequest::RequestParse(void*arg) { int n; int again_flag = true; //again flag decide to close the fd or try again while(true) { errno = 0; //this is important memset(usr_buf,0,RIO_BUFSIZE); //reset the buf n = rio_readn(fd,(void*)usr_buf,RIO_BUFSIZE-1); if(n==-1) { debug("error."); again_flag = false; break; } else if(n==0) { if(errno==EAGAIN) { //debug("again read"); again_flag = true; } else //EOF { //debug("EOF read close fd"); again_flag = false; } //debug("there is not any more data,errno is: %d",errno); break; } read_data = usr_buf; /* cout<<"read data:--------------------------------------------"<<endl; cout<<read_data<<endl; cout<<"-------------------------------------------------------"<<endl; */ //debug_cpp(read_data.size()); CommandParse(); //requese line parse HeaderParse(); //head parse //int data_n = read_data.size(); if(read_data.size()!=0) { BodyParse(); //body parse } /*parse complete,do method,url ,version check*/ HttpError e; int check_res = e.RequireCheck(command,head,out,file_stat); if(check_res!=D_OK) { //debug("require error: %d",check_res); //then send the wrong information page command.uri = "/40x.html"; // reset the file_stat; string file_name = file_root+command.uri; stat(file_name.c_str(),&file_stat); out.SetStaticServer(true); } /**********check over,send the result to the client********/ if(out.GetStaticServer()) { //set the length out.SetFileSize(file_stat.st_size); auto out_line = out.SetOutLine_C(); out_line += out.SetOutHeaders_C(head); char* res_line_buf = const_cast<char*>(out_line.c_str()); n = rio_writen(fd,(void*)res_line_buf,strlen(res_line_buf)); //write command line //debug("send Response line and Out Header."); StaticServer(); //debug("----------static server over-----------"); } else //dynamic server { //debug("----------dynamic server on-------------"); DynamicServer(); //debug("----------dynamic server over-----------"); } //server -------**over**---------- if(head.head.find("Connection")==head.head.end()) //keep alive { again_flag = false; //debug("-----------no keep alive,will break---------"); break; } else { again_flag = true; } } if(!again_flag) { //debug("close fd ,%d",fd); close(fd); //close fd ,there is no other request } else { head.head.clear(); //clear the request head read_data=""; again_flag = true; out.clear(); //clear the output data InitHttpRequest(ep,fd,epfd); //no need to initialize.because the ep,fd,and the epfd etc do not change ep->SetEpollEvent((void*)this,D_EPOLLIN|D_EPOLLET|D_EPOLLONESHOT); //set event ep->EpollCTL(D_EPOLL_CTL_MOD,fd); //add fd to the event module } return NULL; }