#include #include #include #include #include #include #include #include #include "httpd_sim.h" #include #include #include "../version.h" #define SESSION_ID "1234567890ab" #define PASSWORD "1234" #define SESSION_TIMEOUT 2000 #define PORTS 6 #define NSFP 1 #define N_COUNTERS 52 #if PORTS == 9 const uint8_t physToLogPort[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8}; #else const uint8_t physToLogPort[] = { 4, 5, 6, 7, 3, 8}; #endif struct l2_entry { char mac[18]; char vlan[4]; char type; uint8_t port; uint16_t idx; }; #define L2_ENTRY_NUM 12 #define L2_MAX_TRANSFER 5 const struct l2_entry l2_entries[12] = { { "00:01:2f:00:00:01", "001", 'l', 7, 0x10 }, { "00:06:78:00:00:02", "001", 'l', 7, 0x20 }, { "00:01:2e:00:00:03", "001", 's', 7, 0x30 }, { "60:7d:09:00:00:04", "001", 'l', 7, 0x40 }, { "1c:2a:a3:00:00:05", "001", 'l', 7, 0x50 }, { "1c:2a:a3:00:00:06", "001", 's', 7, 0x60 }, { "02:e0:4c:00:00:07", "001", 'l', 7, 0x70 }, { "00:e0:4c:00:00:08", "001", 'l', 4, 0x80 }, { "1c:2a:a3:00:00:09", "001", 'l', 9, 0x90 }, // CPU-Port { "3c:8c:f8:00:00:0a", "001", 'l', 7, 0xa0 }, { "00:01:2e:00:00:0b", "001", 'l', 7, 0xb0 }, { "00:01:2f:00:01:01", "001", 'l', 7, 0xc0 } }; time_t last_called; time_t last_session_use; uint64_t txG[PORTS], txB[PORTS], rxG[PORTS], rxB[PORTS]; char txG_buff[20], txB_buff[20], rxG_buff[20], rxB_buff[20], counter_buf[20], counter_name[20]; char sfp_temp[8], sfp_vcc[8], sfp_txbias[8], sfp_txpower[8], sfp_rxpower[8], sfp_laser[8], sfp_options[6]; char num_buff[20]; char l2_idx_buff[20]; char upload_buffer[4194304]; // 4MB char *content_type = NULL; char boundary[72]; char cmd_history[1024][256]; uint16_t cmd_ptr = 0; char *uploaded_config = NULL; int uploaded_config_len; const char *session = NULL; bool authenticated = false; char is_word(char *c, char *d) { uint8_t i = 0; while (d[i] && (d[i] == c[i])) i++; if (d[i]) return 0; if (c[i] != ' ' && c[i] != '\t' && c[i] != ':' && c[i] != '?' && c[i] != '=' && c[i] != '\n' && c[i] != '\r' && c[i]) return 0; return 1; } int hasSuffix(const char *str, const char *suffix) { if (!str || !suffix) return 0; size_t lenstr = strlen(str); size_t lensuffix = strlen(suffix); if (lensuffix > lenstr) return 0; return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0; } char *getMime(const char *name) { if (hasSuffix(name, ".html")) return "text/html"; else if (hasSuffix(name, ".svg")) return "image/svg+xml"; else if (hasSuffix(name, ".ico")) return "image/svg+xml"; else if (hasSuffix(name, ".png")) return "image/png"; else if (hasSuffix(name, ".js")) return "text/javascript"; else if (hasSuffix(name, ".css")) return "text/css"; return "text/plain"; } void send_basic_info(int socket) { char *response = "HTTP/1.1 200 OK\r\n" "Content-Type: application/json; charset=UTF-8\r\n\r\n" "{\"ip_address\":\"192.168.10.247\",\"ip_gateway\":\"192.168.2.22\",\"ip_netmask\":\"255.255.255.0\",\"mac_address\":\"1c:2a:a3:23:00:02\",\"sw_ver\":\"" VERSION_SW "\",\"hw_ver\":\"SWGT024-V2.0\"" ",\"dhcp_client\":1,\"dhcp_server\":0}"; write(socket, response, strlen(response)); } void send_vlan(int s, int vlan) { struct json_object *v; const char *jstring; char *header = "HTTP/1.1 200 OK\r\n" "Content-Type: application/json; charset=UTF-8\r\n\r\n"; v = json_object_new_object(); sprintf(num_buff, "0x%08x", 0x00060011); json_object_object_add(v, "members", json_object_new_string(num_buff)); write(s, header, strlen(header)); jstring = json_object_to_json_string_ext(v, JSON_C_TO_STRING_PLAIN); write(s, jstring, strlen(jstring)); json_object_put(v); } void send_status(int s) { struct json_object *ports, *v; const char *jstring; char *header = "HTTP/1.1 200 OK\r\n" "Cache-Control: no-cache\r\n" "Content-Type: application/json; charset=UTF-8\r\n\r\n"; printf("Sending status.\n"); time_t now = time(NULL); now = last_called ? last_called + 1 : now; // Make sure we don't divide by 0 for rates ports = json_object_new_array_ext(PORTS); for (int i = 1; i <= PORTS; i++) { v = json_object_new_object(); json_object_object_add(v, "portNum", json_object_new_int(i)); json_object_object_add(v, "logPort", json_object_new_int(physToLogPort[i-1])); json_object_object_add(v, "isSFP", json_object_new_int(i <= PORTS - NSFP ? 0 : 1)); json_object_object_add(v, "enabled", json_object_new_int((i % 4) ? 1 : 0)); json_object_object_add(v, "link", json_object_new_int(i % 2 ? ((i == 1)? 5 : 2) : 0)); if (i % 2) { uint64_t rate = (i == 1) ? 2400000000 : 950000000; txG[i-1] += rate * (now - last_called); rxG[i-1] += rate * (now - last_called); txB[i-1] += rate * (now - last_called) / 10000000; rxB[i-1] += rate * (now - last_called) / 10000000; } sprintf(txG_buff, "0x%016lx", txG[i-1]); sprintf(txB_buff, "0x%016lx", txB[i-1]); sprintf(rxG_buff, "0x%016lx", rxG[i-1]); sprintf(rxB_buff, "0x%016lx", rxB[i-1]); json_object_object_add(v, "txG", json_object_new_string(txG_buff)); json_object_object_add(v, "txB", json_object_new_string(txB_buff)); json_object_object_add(v, "rxG", json_object_new_string(rxG_buff)); json_object_object_add(v, "rxB", json_object_new_string(rxB_buff)); if (i >= PORTS - NSFP) { uint16_t temp = 0x28fb + rand() / (RAND_MAX / 100); uint16_t vcc = 0x7eda + rand() / (RAND_MAX / 100); uint16_t txbias = 0x0d24 +rand() / (RAND_MAX / 100); uint16_t txpower = 0x14bd + rand() / (RAND_MAX / 100); uint16_t rxpower = 0; uint16_t laser = 0; uint16_t options = 0x68; sprintf(sfp_options, "0x%02x", options); sprintf(sfp_temp, "0x%04x", temp); sprintf(sfp_vcc, "0x%04x", vcc); sprintf(sfp_txbias, "0x%04x", txbias); sprintf(sfp_txpower, "0x%04x", txpower); sprintf(sfp_rxpower, "0x%04x", rxpower); sprintf(sfp_laser, "0x%04x", laser); json_object_object_add(v, "sfp_vendor", json_object_new_string("OEM")); json_object_object_add(v, "sfp_model", json_object_new_string("10G-SFP+")); json_object_object_add(v, "sfp_serial", json_object_new_string("12345678")); json_object_object_add(v, "sfp_options", json_object_new_string(sfp_options)); json_object_object_add(v, "sfp_temp", json_object_new_string(sfp_temp)); json_object_object_add(v, "sfp_vcc", json_object_new_string(sfp_vcc)); json_object_object_add(v, "sfp_txbias", json_object_new_string(sfp_txbias)); json_object_object_add(v, "sfp_txpower", json_object_new_string(sfp_txpower)); json_object_object_add(v, "sfp_rxpower", json_object_new_string(sfp_rxpower)); json_object_object_add(v, "sfp_laser", json_object_new_string(sfp_laser)); } else { if (i == 1) json_object_object_add(v, "adv", json_object_new_string("100000")); else if (i==2) json_object_object_add(v, "adv", json_object_new_string("000011")); else json_object_object_add(v, "adv", json_object_new_string("000100")); } json_object_array_add(ports, v); } last_called = now; write(s, header, strlen(header)); jstring = json_object_to_json_string_ext(ports, JSON_C_TO_STRING_PLAIN); write(s, jstring, strlen(jstring)); json_object_put(v); } void send_counters(int s, int port) { struct json_object *counters; const char *jstring; char *header = "HTTP/1.1 200 OK\r\n" "Cache-Control: no-cache\r\n" "Content-Type: application/json; charset=UTF-8\r\n\r\n"; printf("Sending counters\n"); counters = json_object_new_array_ext(N_COUNTERS); for (int i = 0; i < N_COUNTERS; i++) { sprintf(counter_buf, "0x%016lx", 0x1234UL + i); json_object_array_add(counters, json_object_new_string(counter_buf)); } write(s, header, strlen(header)); jstring = json_object_to_json_string_ext(counters, JSON_C_TO_STRING_PLAIN); write(s, jstring, strlen(jstring)); json_object_put(counters); } void send_eee(int s) { struct json_object *ports, *v; const char *jstring; char *header = "HTTP/1.1 200 OK\r\n" "Content-Type: application/json; charset=UTF-8\r\n\r\n"; ports = json_object_new_array_ext(PORTS); for (int i = 1; i <= PORTS; i++) { v = json_object_new_object(); json_object_object_add(v, "portNum", json_object_new_int(i)); json_object_object_add(v, "isSFP", json_object_new_int(i < 5 ? 0 : 1)); uint8_t eee = 0; eee |= 0x02; char eee_buf[20]; sprintf(eee_buf, "%08b", eee); json_object_object_add(v, "eee", json_object_new_string(eee_buf)); uint8_t eee_lp = 0; eee_lp |= 0x04; sprintf(eee_buf, "%08b", eee_lp); json_object_object_add(v, "eee_lp", json_object_new_string(eee_buf)); json_object_object_add(v, "active", json_object_new_int((i % 2) ? 1 : 0)); json_object_array_add(ports, v); } write(s, header, strlen(header)); jstring = json_object_to_json_string_ext(ports, JSON_C_TO_STRING_PLAIN); write(s, jstring, strlen(jstring)); json_object_put(ports); } void send_bandwidth(int s) { struct json_object *ports, *v; const char *jstring; uint32_t bw; int limited, fcEnabled; char *header = "HTTP/1.1 200 OK\r\n" "Content-Type: application/json; charset=UTF-8\r\n\r\n"; ports = json_object_new_array_ext(PORTS); for (int i = 1; i <= PORTS; i++) { v = json_object_new_object(); json_object_object_add(v, "portNum", json_object_new_int(i)); if (i % 2) { limited = 1; fcEnabled = i % 4 ? 1 : 0; bw = 0x100; } else { limited = 0; fcEnabled = 0; bw = 0xfffff; } char bw_buf[20]; sprintf(bw_buf, "%08x", bw); json_object_object_add(v, "iLimited", json_object_new_int(limited)); json_object_object_add(v, "iFC", json_object_new_int(fcEnabled)); json_object_object_add(v, "iBW", json_object_new_string(bw_buf)); if (i % 4) { limited = 1; bw = 0x1000; } else { limited = 0; bw = 0xfffff; } sprintf(bw_buf, "%08x", bw); json_object_object_add(v, "eLimited", json_object_new_int(limited)); json_object_object_add(v, "eBW", json_object_new_string(bw_buf)); json_object_array_add(ports, v); } write(s, header, strlen(header)); jstring = json_object_to_json_string_ext(ports, JSON_C_TO_STRING_PLAIN); write(s, jstring, strlen(jstring)); json_object_put(ports); } void send_mirror(int s) { uint16_t mirror_tx, mirror_rx = 0; char mirror_tx_buf[20]; char mirror_rx_buf[20]; struct json_object *mirror; const char *jstring; char *header = "HTTP/1.1 200 OK\r\n" "Content-Type: application/json; charset=UTF-8\r\n\r\n"; mirror = json_object_new_object(); json_object_object_add(mirror, "mPort", json_object_new_int(1)); json_object_object_add(mirror, "enabled", json_object_new_int(1)); mirror_tx = 0b000110; mirror_rx = 0b000010; sprintf(mirror_tx_buf, "%016b", mirror_tx); sprintf(mirror_rx_buf, "%016b", mirror_rx); json_object_object_add(mirror, "mirror_tx", json_object_new_string(mirror_tx_buf)); json_object_object_add(mirror, "mirror_rx", json_object_new_string(mirror_rx_buf)); write(s, header, strlen(header)); jstring = json_object_to_json_string_ext(mirror, JSON_C_TO_STRING_PLAIN); write(s, jstring, strlen(jstring)); json_object_put(mirror); } void send_l2(int s, int idx) { struct json_object *entries, *v; const char *jstring; char *header = "HTTP/1.1 200 OK\r\n" "Content-Type: application/json; charset=UTF-8\r\n\r\n"; entries = json_object_new_array(); // We find the next entry to transfer based on the index printf("Starting with idx %04x\n", idx); int j = 0; while (j < L2_ENTRY_NUM && l2_entries[j].idx < idx) j++; printf("First entry %d, idx: %04x\n", j, l2_entries[j].idx); int transferred = 0; while ((j < L2_ENTRY_NUM + 1) && (transferred < L2_MAX_TRANSFER)) { // if (rand() / (RAND_MAX / 2) >= 1) // continue; int i = j % L2_ENTRY_NUM; printf("Entry %d, idx: %04x, transferred %d\n", i, l2_entries[i].idx, transferred); v = json_object_new_object(); json_object_object_add(v, "mac", json_object_new_string(l2_entries[i].mac)); json_object_object_add(v, "vlan", json_object_new_string(l2_entries[i].vlan)); if (l2_entries[i].type == 'l') json_object_object_add(v, "type", json_object_new_string("l")); else json_object_object_add(v, "type", json_object_new_string("s")); json_object_object_add(v, "port", json_object_new_int(l2_entries[i].port)); sprintf(l2_idx_buff, "%04x", l2_entries[i].idx); json_object_object_add(v, "idx", json_object_new_string(l2_idx_buff)); json_object_array_add(entries, v); j++; transferred++; printf("j %d, transferred %d\n", j, transferred); } write(s, header, strlen(header)); jstring = json_object_to_json_string_ext(entries, JSON_C_TO_STRING_PLAIN); write(s, jstring, strlen(jstring)); json_object_put(entries); } void send_lag(int s) { char lag_buf[20]; struct json_object *lags = json_object_new_array_ext(4); struct json_object *v; const char *jstring; char *header = "HTTP/1.1 200 OK\r\n" "Content-Type: application/json; charset=UTF-8\r\n\r\n"; for (int i = 0; i < 4; i++) { v = json_object_new_object(); json_object_object_add(v, "lagNum", json_object_new_int(i)); sprintf(lag_buf, "%016b", 0x30 << (i * 2) & 0x1f8); json_object_object_add(v, "members", json_object_new_string(lag_buf)); json_object_object_add(v, "hash", json_object_new_string("0x7e")); json_object_array_add(lags, v); } write(s, header, strlen(header)); jstring = json_object_to_json_string_ext(lags, JSON_C_TO_STRING_PLAIN); write(s, jstring, strlen(jstring)); json_object_put(lags); } void send_mtu(int s) { struct json_object *mtus, *v; const char *jstring; char *header = "HTTP/1.1 200 OK\r\n" "Content-Type: application/json; charset=UTF-8\r\n\r\n"; mtus = json_object_new_array_ext(PORTS); char mtu[8]; for (int i = 1; i <= PORTS; i++) { v = json_object_new_object(); json_object_object_add(v, "portNum", json_object_new_int(i)); sprintf(mtu, "0x%04x", i % 2 ? 16383 : 1522); json_object_object_add(v, "mtu", json_object_new_string(mtu)); json_object_array_add(mtus, v); } write(s, header, strlen(header)); jstring = json_object_to_json_string_ext(mtus, JSON_C_TO_STRING_PLAIN); write(s, jstring, strlen(jstring)); json_object_put(mtus); } void send_cmd_log(int s) { char *header = "HTTP/1.1 200 OK\r\n" "Content-Type: text/plain; charset=UTF-8\r\n\r\n"; write(s, header, strlen(header)); for (int i = 0; i < cmd_ptr; i++) { write(s, cmd_history[i], strlen(cmd_history[i])); write(s, "\n", 1); printf("%d: %s\n", i, cmd_history[i]); } } void send_config(int s) { char *header = "HTTP/1.1 200 OK\r\n" "Content-Type: text/plain; charset=UTF-8\r\n\r\n"; printf("Sending uploaded config\n"); write(s, header, strlen(header)); printf("Uploaded config len: %d\n", uploaded_config_len); printf(">%s<", uploaded_config); write(s, uploaded_config, uploaded_config_len); } struct Server serverConstructor(int port, void (*launch)(struct Server *server)) { struct Server server; server.domain = AF_INET; server.service = SOCK_STREAM; server.port = port; server.protocol = 0; server.backlog = 10; server.address.sin_family = server.domain; server.address.sin_port = htons(port); server.address.sin_addr.s_addr = htonl(INADDR_ANY); server.socket = socket(server.domain, server.service, server.protocol); if (server.socket < 0) { perror("Failed to initialize/connect to socket...\n"); exit(EXIT_FAILURE); } if (bind(server.socket, (struct sockaddr*)&server.address, sizeof(server.address)) < 0) { perror("Failed to bind socket...\n"); exit(EXIT_FAILURE); } if (listen(server.socket, server.backlog) < 0) { perror("Failed to start listening...\n"); exit(EXIT_FAILURE); } server.launch = launch; return server; } void send_not_found(int socket) { char *response = "HTTP/1.1 404 Not found\r\n" "Content-Type: text/html\r\n\r\n" " Not Found" "

Not found!

"; write(socket, response, strlen(response)); } void send_bad_request(int socket) { char *response = "HTTP/1.1 400 Bad Request\r\n" "Content-Type: text/html\r\n\r\n" " Bad Request" "

Bad Request!

"; write(socket, response, strlen(response)); } void send_to_login(int socket) { char *response = "HTTP/1.1 302 Found\r\n" "Location: login.html\r\n\r\n"; write(socket, response, strlen(response)); } void send_unauthorized(int socket) { char *response = "HTTP/1.1 401 Unauthorized\r\n\r\n"; write(socket, response, strlen(response)); } char *scan_header(char *p) { session = 0; authenticated = false; while (*p != '\r' || *(p + 1) != '\n' || *(p + 2) != '\r' || *(p + 3) != '\n') { if (!*p++) break; if (is_word(p, "\nContent-Type:")) content_type = p + 15; else if (is_word(p, "\nCookie:")) session = p + 17; } if (content_type && is_word(content_type, "multipart/form-data; boundary")) { printf("Found multiplart\n"); content_type += 30; uint8_t i = 0; while (content_type[i] != '\r' && content_type[i] != '\n') { boundary[i + 2] = content_type[i]; i++; } // The boundary between parts is "--" + the boundary given in the header boundary[0] = '-'; boundary[1] = '-'; boundary[i + 2] = 0; } time_t now = time(NULL); if (session) { printf("Session: >%s<. time now: %ld last %ld\n", session, now, last_session_use); if (now - last_session_use > SESSION_TIMEOUT) { printf("Session expired\n"); } else { if (!strncmp(session, SESSION_ID, 12)) authenticated = true; else printf("Invalid session cookie!\n"); } } printf("Time now: %ld last %ld\n", now, last_session_use); return p; } char *skip_boundary(char *p) { while (*p) { if (is_word(p, boundary)) return p + strlen(boundary); p++; } return p; } void print_cmd_history(void) { for (int i = 0; i < cmd_ptr; i++) printf("%d: %s\n", i, cmd_history[i]); } void launch(struct Server *server) { char buffer[BUFFER_SIZE]; FILE *inptr; last_called = time(NULL); for (int i=0; i < PORTS; i++) txG[i] = txB[i] = rxG[i] = rxB[i] = 0; while (1) { printf("=== Waiting for connection on port %d === \n", server->port); int addrlen = sizeof(server->address); int new_socket = accept(server->socket, (struct sockaddr*)&server->address, (socklen_t*)&addrlen); ssize_t bytesRead = read(new_socket, buffer, BUFFER_SIZE - 1); printf("bytesRead: %ld\n", bytesRead); int filesize = 0; char *mime; if (bytesRead > 0) { buffer[bytesRead] = '\0'; // Null terminate the string puts(buffer); if (is_word(buffer, "GET")) { scan_header(buffer); if (!strncmp(&buffer[4], "/status.json", 12)) { printf("Status request\n"); if (!authenticated) send_unauthorized(new_socket); else send_status(new_socket); goto done; } else if (!strncmp(&buffer[4], "/eee.json", 9)) { printf("EEE request\n"); if (!authenticated) send_unauthorized(new_socket); else send_eee(new_socket); goto done; } else if (!strncmp(&buffer[4], "/bandwidth.json", 15)) { printf("Bandwidth request\n"); if (!authenticated) send_unauthorized(new_socket); else send_bandwidth(new_socket); goto done; } else if (!strncmp(&buffer[4], "/information.json", 17)) { printf("Status request\n"); if (!authenticated) send_unauthorized(new_socket); else send_basic_info(new_socket); goto done; } else if (!strncmp(&buffer[4], "/mirror.json", 12)) { printf("Mirror request\n"); if (!authenticated) send_unauthorized(new_socket); else send_mirror(new_socket); goto done; } else if (!strncmp(&buffer[4], "/lag.json", 9)) { printf("LAG request\n"); if (!authenticated) send_unauthorized(new_socket); else send_lag(new_socket); goto done; } else if (!strncmp(&buffer[4], "/l2.json?idx=", 13)) { int idx = atoi(&buffer[17]); printf("L2 request\n"); if (!authenticated) send_unauthorized(new_socket); else send_l2(new_socket, idx); goto done; } else if (!strncmp(&buffer[4], "/mtu.json", 9)) { printf("MTU request\n"); if (!authenticated) send_unauthorized(new_socket); else send_mtu(new_socket); goto done; } else if (!strncmp(&buffer[4], "/vlan.json?vid=", 15)) { int vlan = atoi(&buffer[19]); printf("VLAN request for %d\n", vlan); if (!authenticated) send_unauthorized(new_socket); else send_vlan(new_socket, vlan); goto done; } else if (!strncmp(&buffer[4], "/cmd_log", 8)) { printf("Request cmd_log\n"); if (!authenticated) send_unauthorized(new_socket); else send_cmd_log(new_socket); goto done; } else if (!strncmp(&buffer[4], "/config ", 8) && uploaded_config) { printf("Request current config.\n"); if (!authenticated) send_unauthorized(new_socket); else send_config(new_socket); goto done; } else if (!strncmp(&buffer[4], "/counters.json?port=", 20)) { int port = atoi(&buffer[24]); printf("Counters request for %d\n", port); if (!authenticated) send_unauthorized(new_socket); else send_counters(new_socket, port); goto done; } if (!authenticated && !(!strncmp(&buffer[4], "/login.html", 11) || !strncmp(&buffer[4], "/style.css", 10))) { send_to_login(new_socket); goto done; } // A web-page is actively accessed, we can reset session time-out last_session_use = time(NULL); int i = 0; while (!isspace(buffer[4 + i])) i++; buffer[4+i] = '\0'; printf("Serving file: >%s<, name length %d\n", &buffer[5], i); if (i > 1) inptr = fopen(&buffer[5], "rb"); else inptr = fopen("/index.html", "rb"); if (inptr == NULL) { printf("Cannot open input file %s\n", &buffer[5]); send_not_found(new_socket); goto done; } mime = getMime(&buffer[5]); printf("MIME type: %s\n", mime); fseek(inptr, 0L, SEEK_END); filesize = ftell(inptr); printf("Filesize: %d\n", filesize); rewind(inptr); printf("Input file size: %d\n", filesize); if (filesize > BUFFER_SIZE) { printf("File too large.\n"); goto done; } size_t bytes_read = fread(buffer, 1, sizeof(buffer), inptr); printf("Bytes read: %ld\n", bytes_read); if (bytes_read != filesize) { printf("Error reading input file.\n"); goto done; } fclose(inptr); } else if (is_word(buffer, "POST")) { printf("POST request\n"); // Find end of request header char *p = buffer; boundary[0] ='\0'; p = scan_header(p); printf("Boundary: >%s<\n", boundary); if (!*p || !content_type) { printf("Bad request, no content type!\n"); send_bad_request(new_socket); goto done; } if (!authenticated && !is_word(&buffer[5], "/login")) { send_unauthorized(new_socket); goto done; } printf("Bytes read %ld\n", bytesRead); if (is_word(&buffer[5], "/cmd")) { printf("POST cmd\n"); printf("CMD: %s\n", p + 4); strcpy(cmd_history[cmd_ptr], p + 4); cmd_ptr++; print_cmd_history(); char *response = "HTTP/1.1 200 OK\r\n" "Content-Type: text/html\r\n\r\n" " Upload OK" "

Command executed successully

"; write(new_socket, response, strlen(response)); goto done; } else if (is_word(&buffer[5], "/login")) { printf("POST login\n"); p += 4; p += 4; // Read also over "pwd=" char *response; if (is_word(p, PASSWORD)) { printf("Password accepted!\n"); response = "HTTP/1.1 302 Found\r\n" "Location: index.html\r\n" "Set-Cookie: session=" SESSION_ID "; SameSite=Strict\r\n"; } else { response = "HTTP/1.1 302 Found\r\n" "Location: login.html\r\n\r\n"; } write(new_socket, response, strlen(response)); goto done; } else if (is_word(&buffer[5], "/upload") || is_word(&buffer[5], "/config")) { printf("POST upload/config request\n"); bool config_upload = false; if (is_word(&buffer[5], "/config")) config_upload = true; if (!boundary[0]) { printf("Bad request, no boundary!\n"); send_bad_request(new_socket); goto done; } // We skip the intial parts as part of the header do { p = skip_boundary(p); if (!*p) goto bad_request; p = scan_header(p); if (!*p || !content_type) goto bad_request; } while (!is_word(content_type, "application/octet-stream")); printf("Have content: >%s<\n", content_type); p += 4; // Skip \r\n\r\n after content type char *uptr = upload_buffer; int bindex = 0; int bptr = p - buffer; do { if (bptr >= bytesRead) { bptr = 0; bytesRead = read(new_socket, buffer, BUFFER_SIZE - 1); printf("bytesRead: %ld\n", bytesRead); if (!bytesRead) break; } if (!boundary[bindex]) break; if (buffer[bptr] == boundary[bindex]) { bptr++; bindex++; } else { for (int i = 0; i < bindex; i++) *uptr++ = boundary[i]; *uptr++ = buffer[bptr++]; bindex = 0; } } while(1); printf("Done reading\n"); printf("%s", upload_buffer); if (!bindex || boundary[bindex]) goto bad_request; char *response = "HTTP/1.1 200 OK\r\n" "Content-Type: text/html\r\n\r\n" " Upload OK" "

File uploaded successully

"; write(new_socket, response, strlen(response)); if (config_upload) { uploaded_config_len = (uptr - upload_buffer); if (uploaded_config) free (uploaded_config); uploaded_config = malloc(uploaded_config_len + 1); memcpy(uploaded_config, upload_buffer, uploaded_config_len); } goto done; } } char *response = "HTTP/1.1 200 OK\r\n" "Cache-Control: max-age=60, must-revalidate\r\n" "Content-Type: "; write(new_socket, response, strlen(response)); write(new_socket, mime, strlen(mime)); response = "; charset=UTF-8\r\n\r\n"; write(new_socket, response, strlen(response)); if (filesize) write(new_socket, buffer, filesize); } else if (bytesRead == 0) { printf("EOF\n"); continue; } else { perror("Error reading buffer, nothing read...\n"); } done: close(new_socket); continue; bad_request: printf("Bad request!\n"); send_bad_request(new_socket); close(new_socket); } } int main() { // Make sure we can handle writes to a dead client without a signal handler signal(SIGPIPE, SIG_IGN); struct Server server = serverConstructor(8080, launch); server.launch(&server); return 0; }