//**************************************************************** //** ** //** PHilip RUshik. 2010,2011,2012,2013 ** //** Distributed under the terms of the Beerware License ** //** Philip Rushik wrote this code. As long as you retain ** //** this notice, you can do whatever you want with this ** //** stuff. If we meet someday, and you think this stuff ** //** is worth it, you can buy me a beer in return. ** //** --Philip Rushik ** //** ** //** HTTP Server ** //** ** //** Serves files via the HTTP 1.0 protocol. ** //** ** //**************************************************************** #include #include #include #include #include #include #include #include #include #include #include #include #include struct http_request { unsigned char * METHOD, * URI; float VERSION; }; struct http_status { float VERSION; unsigned short int CODE; unsigned char * REASON; }; struct http_body { unsigned int LENGTH; unsigned char * DATA; }; void usage() { printf("HTTP 1.0 Server v0.3\nWritten by Philip Rushik\n"); printf("\n"); printf("USAGE: server [options]\n\nOptions:\n"); printf("\t-h\t\t---\tShow Help\n"); printf("\t-p \t---\tUse alternate port number [default: 80]\n"); printf("\t-d \t---\tStart in different directory [default: ./]\n"); printf("\t-f \t---\tServe specified file regardless of request\n"); printf("\t-i \t\t---\tUse the IP address of (network interface) [default: eth0]\n"); printf("\t-x\t\t---\tKill server after one connection [default: enabled]\n"); printf("\t-c\t\t---\tServe unlimited connections\n"); printf("\t-q\t\t---\tQuiet, don't print progress [default: disabled]\n"); return; } void error(unsigned char *msg) { printf("%s\n",msg); exit(1); return; } struct http_request * parse_http_request(unsigned char *packet) { //HTTP REQUEST FORMAT // // // = GET POST HEAD // = Path to resource // = HTTP/x.xx struct http_request *request; request = malloc(sizeof(struct http_request)); int i; for (i=0;packet[i]!=' ' && packet[i]!='\0';i++) ; request->METHOD=malloc(i); for (;packet[i]!=' ' && packet[i]!='\0';i++) ; request->URI=malloc(i); int k = sscanf(packet,"%s %s HTTP/%f",request->METHOD,request->URI,&request->VERSION); return request; } //This function blindly sends an entire file. It does not check the file size void send_http_file(int sock, int bsize, unsigned char * fname, int quiet) { unsigned char data[bsize]; int i; off_t size; int fd; char relfname[strlen(fname)+2]; sprintf(relfname,"./%s",fname); fd = open(relfname,O_RDONLY,"rb"); if (fd<0) { printf("FAILED: %s\n",fname); write(sock,"HTTP/1.0 404 NA\r\n\r\n

404: Not Found

",56); return; } struct stat stbuf; if (fstat(fd, &stbuf)==-1) printf("Error\n"); size=stbuf.st_size; char head[100]; sprintf(head,"HTTP/1.0 200 OK\r\nContent-Type: application/octet-stream\r\nContent-Length: %d\r\n\r\n",size); if (!quiet) printf("SENDING: %s (%d)\n",fname,size); write(sock,head,strlen(head)); // write(sock,"HTTP/1.0 200 OK\r\n\r\n",19); printf("\n"); int progress=0; do { i=read(fd,data,bsize); write(sock,data,i); progress+=i; if (!quiet) printf("\033[F\033[J"); // Calculuate the ratio of complete-to-incomplete. float ratio = progress/(float)size; int c = ratio * 50; // Show the percentage complete. if (!quiet) { printf("%d/%d (%3d%%) [", progress, size, (int)(ratio*100) ); // Show the load bar. int x; for (x=0; xsin_addr),port,rname); return; } int main(int argc, char **argv) { int sockfd, clilen, openfd; unsigned char buffer[512], *data; //How big should the buffer be? struct sockaddr_in serv_addr, cli_addr; int i,n,port=80,num=1,quiet=0; char *resp=NULL; char *ifname="eth0"; if (argc==1) { usage(); exit(0); } for (i=0;iURI,quiet); free(req); close(openfd); } return 0; }