/* SlideScript - minimalistic top-down scripting language. (C) Copyright 2014-2021 Chris Dorman - some rights reserved (GPLv2) View README file supplied with this software for more details */ #include "inc/deps.h" #include "inc/network.h" #include "inc/util.h" // Structure of file types for nethttp // mimetype struct, searched through when checking mimetype struct { char *ext; char *filetype; } file_extensions [] = { {"gif", "image/gif" }, {"jpg", "image/jpeg" }, {"jpeg","image/jpeg" }, {"png", "image/png" }, {"zip", "application/zip" }, {"gz", "application/gzip" }, {"tar", "application/x-tar" }, {"htm", "text/html" }, {"html","text/html" }, {"cgi", "text/cgi" }, {"asp","text/asp" }, {"xml", "text/xml" }, {"js", "text/js" }, {"css", "text/css" }, {"c", "text/plain" }, {"h", "text/plain" }, {"md", "text/plain" }, {"txt", "text/plain" }, {"ss", "text/plain" }, {"sh", "text/plain" }, {"ogg", "audio/ogg" }, {"mp3", "audio/mpeg" }, {0,0} }; /* Serve process function, on connection catch buffer from socket */ void snet_process_connection(int sockfd, char *srch, char *resp) { char buff[MAX_STRING_BUFSIZE+1]; int rr, wr; //bzero(buff, MAX_STRING_BUFSIZE); // read the message from client and copy it in buffer rr = read(sockfd, buff, sizeof(buff)); if(rr == -1) syn_error("ss:net:client read error"); // print buffer which contains the client contents printf("ss:net: %s\n", buff); bzero(buff, MAX_STRING_BUFSIZE); // if msg contains "Exit" then server exit and chat ended. if (strncmp("exit", buff, 4) == 0) { syn_error("ss:net:call to exit"); } if (strncmp(srch, buff, strlen(srch)) == 0) { wr = write(sockfd, resp, sizeof(resp)); if(wr == -1) syn_error("ss:error:network write error!"); } else { wr = write(sockfd, resp, sizeof(resp)); if(wr == -1) syn_error("ss:error:network write error!"); } } /* Main netlisten function */ void snet_listen(int port, char *srch, char *resp) { int sockfd, connfd, length; struct sockaddr_in servaddr; struct sockaddr_in cliaddr; // socket create and verification sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { syn_error("ss:error:network socket creation failed"); } bzero(&servaddr, sizeof(servaddr)); // assign IP, PORT servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(port); // Binding newly created socket to given IP and verification if ((bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr))) != 0) { syn_error("ss:error:network bind failed"); } // Now server is ready to listen and verification if ((listen(sockfd, 64)) != 0) { syn_error("ss:error:network listen failed"); } else { printf("ss:net:listening on '%d'\n", port); } for( ; ; ) { length = sizeof(cliaddr); // Accept the data packet from client and verification if((connfd = accept(sockfd, (struct sockaddr*)&cliaddr, (socklen_t*) &length)) < 0) { syn_error("ss:error:network accept failed"); } snet_process_connection(connfd, srch, resp); } // After chatting close the socket close(sockfd); } // Main nettoss function void snet_toss(char *address, int port, char *string) { int sockfd; struct sockaddr_in servaddr; // socket create and varification sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { syn_warn("ss:warn:network, failed to create socket"); return; } bzero(&servaddr, sizeof(servaddr)); // assign IP, PORT servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = inet_addr(address); servaddr.sin_port = htons(port); // connect the client socket to server socket if (connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) != 0) { syn_warn("ss:warn:network, failed to connect to socket"); close(sockfd); return; } else { printf("ss:net:connect: %s:%d\n", address, port); } // If write reports -1, exit on error. if(write(sockfd, string, strlen(string)) < 0) syn_warn("ss:warn:network, socket write error!"); // close the socket after pushing content close(sockfd); } // Process connection of nethttp void snet_http_process(int fd, int forkval) { int j, file_fd, buflen, len; long i, filesize; char *fstr = NULL; static char buffer[HTTP_BUFSIZE+1]; // Check to see if file is corrupted filesize = read(fd,buffer,HTTP_BUFSIZE); if(filesize == 0 || filesize == -1) { sprintf(buffer,"HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"); if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error"); sprintf(buffer,"ss:http:missed header

301: Missed header call

" \ "

Could not locate file



ss:http:%s
", VERSION); if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error"); exit(1); } if(filesize > 0 && filesize < HTTP_BUFSIZE) { buffer[filesize]=0; } else { buffer[0]=0; } for(i=0;iss:http: server not implemented" \ "

501: Not Implemented

ss:http only supports simple GET requests via HTTP/1.0

" \ "

ss:http:%s
", VERSION); if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error"); exit(1); } // This gets the file name from "GET /..." for(i=4;iss:http: parent directory not available

FORBIDDEN: parent directory

" \ "

You do not have access to view ../. Blocked.



ss:http:%s
", VERSION); if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error"); exit(1); } } // If client is connecting with GET / (root of website) then send index if( !strncmp(&buffer[0],"GET /\0",6) || !strncmp(&buffer[0],"get /\0",6) ) { if(file_exists("index.html")) { strcpy(buffer,"GET /index.html"); } else { sprintf(buffer,"HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"); if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error"); sprintf(buffer,"ss:http: file not found

File not found

" \ "

Could not locate index.html



ss:http:%s
", VERSION); if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error"); exit(1); } } // Get file mimetype buflen=strlen(buffer); for(i=0;file_extensions[i].ext != 0;i++) { len = strlen(file_extensions[i].ext); if(!strncmp(&buffer[buflen-len], file_extensions[i].ext, len)) { fstr = file_extensions[i].filetype; break; } } if(fstr == NULL) { fstr = "application/octet-stream"; } if(forkval == 0) printf("ss:net:http request %s, %s\n", &buffer[5], fstr); if(is_dir(&buffer[5]) == 1) { sprintf(buffer,"HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"); if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error"); sprintf(buffer,"ss:http: directory

Directory

" \ "

No directory listings at this time...



ss:http:%s
", VERSION); if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error"); exit(1); } // See if the web server can open requested file from browser if(( file_fd = open(&buffer[5],O_RDONLY)) == -1) { sprintf(buffer,"HTTP/1.0 404 Not Found\r\nContent-Type: text/html\r\n\r\n"); if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error"); sprintf(buffer,"ss:http:file not found

404: File not found

" \ "

Could not locate file



ss:http:%s
", VERSION); if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error"); exit(1); } sprintf(buffer,"HTTP/1.0 200 OK\r\nContent-Type: %s\r\n\r\n", fstr); if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error"); while ((filesize = read(file_fd, buffer, HTTP_BUFSIZE)) > 0) { if(write(fd,buffer,filesize) < 0) syn_error("ss:net:http socket write error"); } #ifdef LINUX sleep(1); #endif exit(0); } // Main function for nethttp // void snet_http(int port, int forkval) { // Intergers for ports, sockets, etc int i, pid, listenfd, socketfd, hit; socklen_t length; // structs for socket addresses, these are always needed! static struct sockaddr_in cli_addr; static struct sockaddr_in serv_addr; // This forks the httpd process into the background, if forkval > 0 if(forkval > 0) { if(fork() != 0) syn_error("ss:net:http forked"); #ifndef BSD signal(SIGCLD, SIG_IGN); #endif signal(SIGHUP, SIG_IGN); for(i=0;i<32;i++) { close(i); } } setpgid(0, 0); if(forkval < 1) printf("Starting httpd...\n"); // Check if socket succeeded to open if((listenfd = socket(AF_INET, SOCK_STREAM,0)) <0) { printf("Failed to open socket\n"); exit(1); } // check if valid port number if(port < 0 || port >65534) { syn_error("ss:net:http incorrect port range (vaild 1 - 65534)"); } // binds the socket to a specific port and address // in this case, 0.0.0.0 and the port you choose serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(port); if(bind(listenfd, (struct sockaddr *)&serv_addr,sizeof(serv_addr)) <0) { syn_error("ss:net:http failed to bind to socket"); } if( listen(listenfd,64) <0) { syn_error("ss:net:http failed to listen to socket"); } for(hit=1; ;hit++) { length = sizeof(cli_addr); // Check if server succeeded to accept connection if((socketfd = accept(listenfd, (struct sockaddr *)&cli_addr, &length)) < 0) { syn_error("ss:net:http failed to accept connection"); } // Fork, and die if server fails to fork process if((pid = fork()) < 0) { syn_error("ss:net:http failed to fork connection"); } else { if(pid == 0) { close(listenfd); snet_http_process(socketfd, forkval); } else { close(socketfd); } } } }