123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479 |
- /*
- SlideScript - minimalistic top-down scripting language.
- (C) Copyright 2014-2022 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/lexer.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 */
- char *snet_process_connection(int sockfd)
- {
- char *buff = qmalloc(QM_SS, 1024);
- char *endbuff = qmalloc(QM_SS, 1024);
- int rr, wr, ii;
- bzero(buff, 1024);
- bzero(endbuff, 1024);
- usleep(50000);
- ii = 1;
- // read the message from client and copy it in buffer
- while ( (rr = read(sockfd, buff, 1024)) > 0)
- {
- if(ii > 1)
- {
- endbuff = qrealloc(endbuff, (strlen(endbuff) + 1024));
- //printf("%s\n", buff);
- memcpy(&endbuff[(1024 * ii) - 1024], buff, rr);
- if(rr < 1024) break;
- }
- else
- {
- memcpy(endbuff, buff, rr);
- if(rr < 1024) break;
- }
- if(rr == 1024)
- {
- ii++;
- continue;
- }
- }
- // if msg contains "Exit" then server exit, meets search, respond.
- if (strncmp("exit", buff, 4) == 0)
- {
- wr = write(sockfd, "ss:ok", 5);
- if(wr == -1) syn_warn("ss:warn:network write error");
- syn_warn("ss:server:client called exit");
- return NULL;
- }
- else
- {
- wr = write(sockfd, "ss:ok", 5);
- if(wr == -1) syn_warn("ss:warn:network write error");
- // Get random filename for lastly pushing to save file
- char *randTokenName = malloc(17);
- FILE *socket_save = NULL;
- gen_random_string(randTokenName, 16);
- socket_save = fopen(randTokenName, "wb");
- if(strlen(endbuff) > 0)
- {
- fprintf(socket_save, "%s", endbuff);
- printf("ss:server:client buffer saved as '%s'\n", randTokenName);
- fflush(stdout);
- }
- fclose(socket_save);
- free(randTokenName); // Free malloc, i'm done
- }
- return "ok";
- }
- /* Main netlisten function */
- void snet_listen(int port)
- {
- int sockfd, connfd, length, pid;
- 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:server:listening on '%d'\n", port);
- fflush(stdout);
- }
- length = sizeof(cliaddr);
- // Accept the data packet from client and verification
- while ( (connfd = accept(sockfd, (struct sockaddr*)&cliaddr, (socklen_t*) &length)) )
- {
- char connIp[33];
- struct sockaddr_in* pV4Addr = (struct sockaddr_in*)&cliaddr;
- struct in_addr ipAddr = pV4Addr->sin_addr;
- if((pid = fork()) == -1)
- {
- syn_warn("ss:warn:netlisten failed to fork");
- close(connfd);
- continue;
- }
- else if(pid > 0)
- {
- close(connfd);
- continue;
- }
- else if(pid == 0)
- {
- inet_ntop(AF_INET, &ipAddr, connIp, 32);
- printf("ss:server:connection from %s\n", connIp);
- char *sc_return = snet_process_connection(connfd);
- if(sc_return == NULL)
- {
- break;
- }
- close(connfd);
- }
- }
- // 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:client:connected to %s:%d\n", address, port);
- fflush(stdout);
- }
- // If write reports -1, exit on error.
- if(write(sockfd, string, strlen(string)) < 0)
- {
- syn_warn("ss:warn:nettoss, socket write error!");
- }
- while(sockfd != -1)
- {
- char *buf = malloc(128);
- bzero(buf, 128);
- usleep(500000);
- int listener = read(sockfd, buf, 128);
- if(listener < 0)
- {
- syn_warn("ss:warn:nettoss, server killed socket");
- free(buf);
- break;
- }
- else if(listener > 0)
- {
- if(strncmp("kill", buf, 4) == 0)
- {
- printf("ss:client: server called %s!\n", buf);
- free(buf);
- break;
- }
- else if(strncmp("ss:ok", buf, 5) == 0)
- {
- free(buf);
- fflush(stdout);
- break;
- }
- else
- {
- printf("ss:server: %s\n", buf);
- fflush(stdout);
- free(buf);
- break;
- }
- }
- }
- // 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,"<html><head><title>ss:http:missed header</title></head><body><h2>301: Missed header call</h2>" \
- "<p>Could not locate file</p><br /><br /><center>ss:http:%s</center></body></html>", 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;i<filesize;i++) {
- if(buffer[i] == '\r' || buffer[i] == '\n') {
- buffer[i]='*';
- }
- }
- if(strncmp(buffer,"GET ",4) && strncmp(buffer,"get ",4)) {
- sprintf(buffer,"HTTP/1.0 501 Not Implemented\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,"<html><head><title>ss:http: server not implemented</title></head><body>" \
- "<h2>501: Not Implemented</h2><p>ss:http only supports simple GET requests via HTTP/1.0</p>" \
- "<br /><br /><center>ss:http:%s</center></body></html>", 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;i<HTTP_BUFSIZE;i++) {
- if(buffer[i] == ' ') {
- buffer[i] = 0;
- break;
- }
- }
-
- // Check if connection is trying to view in directories behind webserver root
- for(j=0;j<i-1;j++) {
- if(buffer[j] == '.' && buffer[j+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,"<html><head><title>ss:http: parent directory not available</title></head><body><h2>FORBIDDEN: parent directory</h2>" \
- "<p>You do not have access to view ../. Blocked.</p><br /><br /><center>ss:http:%s</center></body></html>", 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,"<html><head><title>ss:http: file not found</title></head><body><h2>File not found</h2>" \
- "<p>Could not locate index.html</p><br /><br /><center>ss:http:%s</center></body></html>", 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);
- fflush(stdout);
- }
- 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,"<html><head><title>ss:http: directory</title></head><body><h2>Directory</h2>" \
- "<p>No directory listings at this time...</p><br /><br /><center>ss:http:%s</center></body></html>", 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,"<html><head><title>ss:http:file not found</title></head><body><h2>404: File not found</h2>" \
- "<p>Could not locate file</p><br /><br /><center>ss:http:%s</center></body></html>", 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("ss:starting httpd...\n");
- fflush(stdout);
- }
- // Check if socket succeeded to open
- if((listenfd = socket(AF_INET, SOCK_STREAM,0)) <0) {
- printf("ss:network: failed to open socket\n");
- fflush(stdout);
- 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);
- }
- }
- }
- }
|