network.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. /*
  2. SlideScript - minimalistic top-down scripting language.
  3. (C) Copyright 2014-2022 Chris Dorman - some rights reserved (GPLv2)
  4. View README file supplied with this software for more details
  5. */
  6. #include "inc/deps.h"
  7. #include "inc/network.h"
  8. #include "inc/lexer.h"
  9. #include "inc/util.h"
  10. // Structure of file types for nethttp
  11. // mimetype struct, searched through when checking mimetype
  12. struct {
  13. char *ext;
  14. char *filetype;
  15. } file_extensions [] = {
  16. {"gif", "image/gif" },
  17. {"jpg", "image/jpeg" },
  18. {"jpeg","image/jpeg" },
  19. {"png", "image/png" },
  20. {"zip", "application/zip" },
  21. {"gz", "application/gzip" },
  22. {"tar", "application/x-tar" },
  23. {"htm", "text/html" },
  24. {"html","text/html" },
  25. {"cgi", "text/cgi" },
  26. {"asp","text/asp" },
  27. {"xml", "text/xml" },
  28. {"js", "text/js" },
  29. {"css", "text/css" },
  30. {"c", "text/plain" },
  31. {"h", "text/plain" },
  32. {"md", "text/plain" },
  33. {"txt", "text/plain" },
  34. {"ss", "text/plain" },
  35. {"sh", "text/plain" },
  36. {"ogg", "audio/ogg" },
  37. {"mp3", "audio/mpeg" },
  38. {0,0}
  39. };
  40. /* Serve process function, on connection catch buffer from socket */
  41. char *snet_process_connection(int sockfd)
  42. {
  43. char *buff = qmalloc(QM_SS, 1024);
  44. char *endbuff = qmalloc(QM_SS, 1024);
  45. int rr, wr, ii;
  46. bzero(buff, 1024);
  47. bzero(endbuff, 1024);
  48. usleep(50000);
  49. ii = 1;
  50. // read the message from client and copy it in buffer
  51. while ( (rr = read(sockfd, buff, 1024)) > 0)
  52. {
  53. if(ii > 1)
  54. {
  55. endbuff = qrealloc(endbuff, (strlen(endbuff) + 1024));
  56. //printf("%s\n", buff);
  57. memcpy(&endbuff[(1024 * ii) - 1024], buff, rr);
  58. if(rr < 1024) break;
  59. }
  60. else
  61. {
  62. memcpy(endbuff, buff, rr);
  63. if(rr < 1024) break;
  64. }
  65. if(rr == 1024)
  66. {
  67. ii++;
  68. continue;
  69. }
  70. }
  71. // if msg contains "Exit" then server exit, meets search, respond.
  72. if (strncmp("exit", buff, 4) == 0)
  73. {
  74. wr = write(sockfd, "ss:ok", 5);
  75. if(wr == -1) syn_warn("ss:warn:network write error");
  76. syn_warn("ss:server:client called exit");
  77. return NULL;
  78. }
  79. else
  80. {
  81. wr = write(sockfd, "ss:ok", 5);
  82. if(wr == -1) syn_warn("ss:warn:network write error");
  83. // Get random filename for lastly pushing to save file
  84. char *randTokenName = malloc(17);
  85. FILE *socket_save = NULL;
  86. gen_random_string(randTokenName, 16);
  87. socket_save = fopen(randTokenName, "wb");
  88. if(strlen(endbuff) > 0)
  89. {
  90. fprintf(socket_save, "%s", endbuff);
  91. printf("ss:server:client buffer saved as '%s'\n", randTokenName);
  92. fflush(stdout);
  93. }
  94. fclose(socket_save);
  95. free(randTokenName); // Free malloc, i'm done
  96. }
  97. return "ok";
  98. }
  99. /* Main netlisten function */
  100. void snet_listen(int port)
  101. {
  102. int sockfd, connfd, length, pid;
  103. struct sockaddr_in servaddr;
  104. struct sockaddr_in cliaddr;
  105. // socket create and verification
  106. sockfd = socket(AF_INET, SOCK_STREAM, 0);
  107. if (sockfd == -1)
  108. {
  109. syn_error("ss:error:network socket creation failed");
  110. }
  111. bzero(&servaddr, sizeof(servaddr));
  112. // assign IP, PORT
  113. servaddr.sin_family = AF_INET;
  114. servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  115. servaddr.sin_port = htons(port);
  116. // Binding newly created socket to given IP and verification
  117. if ((bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr))) != 0)
  118. {
  119. syn_error("ss:error:network bind failed");
  120. }
  121. // Now server is ready to listen and verification
  122. if ((listen(sockfd, 64)) != 0)
  123. {
  124. syn_error("ss:error:network listen failed");
  125. }
  126. else
  127. {
  128. printf("ss:server:listening on '%d'\n", port);
  129. fflush(stdout);
  130. }
  131. length = sizeof(cliaddr);
  132. // Accept the data packet from client and verification
  133. while ( (connfd = accept(sockfd, (struct sockaddr*)&cliaddr, (socklen_t*) &length)) )
  134. {
  135. char connIp[33];
  136. struct sockaddr_in* pV4Addr = (struct sockaddr_in*)&cliaddr;
  137. struct in_addr ipAddr = pV4Addr->sin_addr;
  138. if((pid = fork()) == -1)
  139. {
  140. syn_warn("ss:warn:netlisten failed to fork");
  141. close(connfd);
  142. continue;
  143. }
  144. else if(pid > 0)
  145. {
  146. close(connfd);
  147. continue;
  148. }
  149. else if(pid == 0)
  150. {
  151. inet_ntop(AF_INET, &ipAddr, connIp, 32);
  152. printf("ss:server:connection from %s\n", connIp);
  153. char *sc_return = snet_process_connection(connfd);
  154. if(sc_return == NULL)
  155. {
  156. break;
  157. }
  158. close(connfd);
  159. }
  160. }
  161. // After chatting close the socket
  162. close(sockfd);
  163. }
  164. // Main nettoss function
  165. void snet_toss(char *address, int port, char *string)
  166. {
  167. int sockfd;
  168. struct sockaddr_in servaddr;
  169. // socket create and varification
  170. sockfd = socket(AF_INET, SOCK_STREAM, 0);
  171. if (sockfd == -1)
  172. {
  173. syn_warn("ss:warn:network, failed to create socket");
  174. return;
  175. }
  176. bzero(&servaddr, sizeof(servaddr));
  177. // assign IP, PORT
  178. servaddr.sin_family = AF_INET;
  179. servaddr.sin_addr.s_addr = inet_addr(address);
  180. servaddr.sin_port = htons(port);
  181. // connect the client socket to server socket
  182. if (connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) != 0)
  183. {
  184. syn_warn("ss:warn:network, failed to connect to socket");
  185. close(sockfd);
  186. return;
  187. }
  188. else
  189. {
  190. printf("ss:client:connected to %s:%d\n", address, port);
  191. fflush(stdout);
  192. }
  193. // If write reports -1, exit on error.
  194. if(write(sockfd, string, strlen(string)) < 0)
  195. {
  196. syn_warn("ss:warn:nettoss, socket write error!");
  197. }
  198. while(sockfd != -1)
  199. {
  200. char *buf = malloc(128);
  201. bzero(buf, 128);
  202. usleep(500000);
  203. int listener = read(sockfd, buf, 128);
  204. if(listener < 0)
  205. {
  206. syn_warn("ss:warn:nettoss, server killed socket");
  207. free(buf);
  208. break;
  209. }
  210. else if(listener > 0)
  211. {
  212. if(strncmp("kill", buf, 4) == 0)
  213. {
  214. printf("ss:client: server called %s!\n", buf);
  215. free(buf);
  216. break;
  217. }
  218. else if(strncmp("ss:ok", buf, 5) == 0)
  219. {
  220. free(buf);
  221. fflush(stdout);
  222. break;
  223. }
  224. else
  225. {
  226. printf("ss:server: %s\n", buf);
  227. fflush(stdout);
  228. free(buf);
  229. break;
  230. }
  231. }
  232. }
  233. // close the socket after pushing content
  234. close(sockfd);
  235. }
  236. // Process connection of nethttp
  237. void snet_http_process(int fd, int forkval)
  238. {
  239. int j, file_fd, buflen, len;
  240. long i, filesize;
  241. char *fstr = NULL;
  242. static char buffer[HTTP_BUFSIZE+1];
  243. // Check to see if file is corrupted
  244. filesize = read(fd,buffer,HTTP_BUFSIZE);
  245. if(filesize == 0 || filesize == -1) {
  246. sprintf(buffer,"HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n");
  247. if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error");
  248. sprintf(buffer,"<html><head><title>ss:http:missed header</title></head><body><h2>301: Missed header call</h2>" \
  249. "<p>Could not locate file</p><br /><br /><center>ss:http:%s</center></body></html>", VERSION);
  250. if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error");
  251. exit(1);
  252. }
  253. if(filesize > 0 && filesize < HTTP_BUFSIZE) {
  254. buffer[filesize]=0;
  255. } else {
  256. buffer[0]=0;
  257. }
  258. for(i=0;i<filesize;i++) {
  259. if(buffer[i] == '\r' || buffer[i] == '\n') {
  260. buffer[i]='*';
  261. }
  262. }
  263. if(strncmp(buffer,"GET ",4) && strncmp(buffer,"get ",4)) {
  264. sprintf(buffer,"HTTP/1.0 501 Not Implemented\r\nContent-Type: text/html\r\n\r\n");
  265. if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error");
  266. sprintf(buffer,"<html><head><title>ss:http: server not implemented</title></head><body>" \
  267. "<h2>501: Not Implemented</h2><p>ss:http only supports simple GET requests via HTTP/1.0</p>" \
  268. "<br /><br /><center>ss:http:%s</center></body></html>", VERSION);
  269. if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error");
  270. exit(1);
  271. }
  272. // This gets the file name from "GET /..."
  273. for(i=4;i<HTTP_BUFSIZE;i++) {
  274. if(buffer[i] == ' ') {
  275. buffer[i] = 0;
  276. break;
  277. }
  278. }
  279. // Check if connection is trying to view in directories behind webserver root
  280. for(j=0;j<i-1;j++) {
  281. if(buffer[j] == '.' && buffer[j+1] == '.') {
  282. sprintf(buffer,"HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n");
  283. if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error");
  284. sprintf(buffer,"<html><head><title>ss:http: parent directory not available</title></head><body><h2>FORBIDDEN: parent directory</h2>" \
  285. "<p>You do not have access to view ../. Blocked.</p><br /><br /><center>ss:http:%s</center></body></html>", VERSION);
  286. if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error");
  287. exit(1);
  288. }
  289. }
  290. // If client is connecting with GET / (root of website) then send index
  291. if( !strncmp(&buffer[0],"GET /\0",6) || !strncmp(&buffer[0],"get /\0",6) ) {
  292. if(file_exists("index.html")) {
  293. strcpy(buffer,"GET /index.html");
  294. } else {
  295. sprintf(buffer,"HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n");
  296. if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error");
  297. sprintf(buffer,"<html><head><title>ss:http: file not found</title></head><body><h2>File not found</h2>" \
  298. "<p>Could not locate index.html</p><br /><br /><center>ss:http:%s</center></body></html>", VERSION);
  299. if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error");
  300. exit(1);
  301. }
  302. }
  303. // Get file mimetype
  304. buflen=strlen(buffer);
  305. for(i=0;file_extensions[i].ext != 0;i++) {
  306. len = strlen(file_extensions[i].ext);
  307. if(!strncmp(&buffer[buflen-len], file_extensions[i].ext, len)) {
  308. fstr = file_extensions[i].filetype;
  309. break;
  310. }
  311. }
  312. if(fstr == NULL)
  313. {
  314. fstr = "application/octet-stream";
  315. }
  316. if(forkval == 0)
  317. {
  318. printf("ss:net:http request %s, %s\n", &buffer[5], fstr);
  319. fflush(stdout);
  320. }
  321. if(is_dir(&buffer[5]) == 1)
  322. {
  323. sprintf(buffer,"HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n");
  324. if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error");
  325. sprintf(buffer,"<html><head><title>ss:http: directory</title></head><body><h2>Directory</h2>" \
  326. "<p>No directory listings at this time...</p><br /><br /><center>ss:http:%s</center></body></html>", VERSION);
  327. if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error");
  328. exit(1);
  329. }
  330. // See if the web server can open requested file from browser
  331. if(( file_fd = open(&buffer[5],O_RDONLY)) == -1) {
  332. sprintf(buffer,"HTTP/1.0 404 Not Found\r\nContent-Type: text/html\r\n\r\n");
  333. if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error");
  334. sprintf(buffer,"<html><head><title>ss:http:file not found</title></head><body><h2>404: File not found</h2>" \
  335. "<p>Could not locate file</p><br /><br /><center>ss:http:%s</center></body></html>", VERSION);
  336. if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error");
  337. exit(1);
  338. }
  339. sprintf(buffer,"HTTP/1.0 200 OK\r\nContent-Type: %s\r\n\r\n", fstr);
  340. if(write(fd,buffer,strlen(buffer)) < 0) syn_error("ss:net:http socket write error");
  341. while ((filesize = read(file_fd, buffer, HTTP_BUFSIZE)) > 0) {
  342. if(write(fd,buffer,filesize) < 0) syn_error("ss:net:http socket write error");
  343. }
  344. #ifdef LINUX
  345. sleep(1);
  346. #endif
  347. exit(0);
  348. }
  349. // Main function for nethttp //
  350. void snet_http(int port, int forkval)
  351. {
  352. // Intergers for ports, sockets, etc
  353. int i, pid, listenfd, socketfd, hit;
  354. socklen_t length;
  355. // structs for socket addresses, these are always needed!
  356. static struct sockaddr_in cli_addr;
  357. static struct sockaddr_in serv_addr;
  358. // This forks the httpd process into the background, if forkval > 0
  359. if(forkval > 0)
  360. {
  361. if(fork() != 0)
  362. syn_error("ss:net:http forked");
  363. #ifndef BSD
  364. signal(SIGCLD, SIG_IGN);
  365. #endif
  366. signal(SIGHUP, SIG_IGN);
  367. for(i=0;i<32;i++) {
  368. close(i);
  369. }
  370. }
  371. setpgid(0, 0);
  372. if(forkval < 1)
  373. {
  374. printf("ss:starting httpd...\n");
  375. fflush(stdout);
  376. }
  377. // Check if socket succeeded to open
  378. if((listenfd = socket(AF_INET, SOCK_STREAM,0)) <0) {
  379. printf("ss:network: failed to open socket\n");
  380. fflush(stdout);
  381. exit(1);
  382. }
  383. // check if valid port number
  384. if(port < 0 || port >65534) {
  385. syn_error("ss:net:http incorrect port range (vaild 1 - 65534)");
  386. }
  387. // binds the socket to a specific port and address
  388. // in this case, 0.0.0.0 and the port you choose
  389. serv_addr.sin_family = AF_INET;
  390. serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  391. serv_addr.sin_port = htons(port);
  392. if(bind(listenfd, (struct sockaddr *)&serv_addr,sizeof(serv_addr)) <0) {
  393. syn_error("ss:net:http failed to bind to socket");
  394. }
  395. if( listen(listenfd,64) <0) {
  396. syn_error("ss:net:http failed to listen to socket");
  397. }
  398. for(hit=1; ;hit++) {
  399. length = sizeof(cli_addr);
  400. // Check if server succeeded to accept connection
  401. if((socketfd = accept(listenfd, (struct sockaddr *)&cli_addr, &length)) < 0) {
  402. syn_error("ss:net:http failed to accept connection");
  403. }
  404. // Fork, and die if server fails to fork process
  405. if((pid = fork()) < 0) {
  406. syn_error("ss:net:http failed to fork connection");
  407. }
  408. else {
  409. if(pid == 0) {
  410. close(listenfd);
  411. snet_http_process(socketfd, forkval);
  412. } else {
  413. close(socketfd);
  414. }
  415. }
  416. }
  417. }