void httpd_main(void) { if (uip_aborted() || uip_timedout()) { printf("httpd: connection aborted\n"); httpd_cleanup(); return; } if (uip_closed()) { printf("httpd: connection closed\n"); httpd_cleanup(); return; } if (uip_connected()) { printf("httpd: new connection\n"); /* initialize struct */ STATE->handler = NULL; STATE->header_acked = 0; STATE->eof = 0; STATE->header_reparse = 0; #ifdef HTTPD_AUTH_SUPPORT STATE->auth_state = PAM_UNKOWN; #endif } if (uip_newdata() && (!STATE->handler || STATE->header_reparse)) { printf("httpd: new data\n"); httpd_handle_input(); } #ifdef HTTPD_AUTH_SUPPORT if (STATE->auth_state == PAM_DENIED && STATE->handler != httpd_handle_401) { httpd_cleanup(); STATE->handler = httpd_handle_401; STATE->header_reparse = 0; printf("httpd: auth failed\n"); } else if (STATE->auth_state == PAM_PENDING) return; /* Waiting for the PAM Layer */ #endif if (uip_rexmit() || uip_newdata() || uip_acked() || uip_poll() || uip_connected()) { /* Call associated handler, if set already. */ if (STATE->handler && (!STATE->header_reparse)) STATE->handler(); } }
void httpd_main(void) { if (uip_aborted() || uip_timedout()) { httpd_cleanup (); printf ("httpd: connection aborted\n"); } if (uip_closed()) { httpd_cleanup (); printf ("httpd: connection closed\n"); } if (uip_connected()) { printf ("httpd: new connection\n"); /* initialize struct */ STATE->handler = NULL; STATE->header_acked = 0; STATE->eof = 0; STATE->header_reparse = 0; } if (uip_newdata() && (!STATE->handler || STATE->header_reparse)) { printf ("httpd: new data\n"); httpd_handle_input (); } if(uip_rexmit() || uip_newdata() || uip_acked() || uip_connected()) { /* Call associated handler, if set already. */ if (STATE->handler && (!STATE->header_reparse)) STATE->handler (); } }
void httpd_handle_vfs_send_body (void) { vfs_fseek (STATE->u.vfs.fd, STATE->u.vfs.acked, SEEK_SET); vfs_size_t len = vfs_read (STATE->u.vfs.fd, uip_appdata, uip_mss ()); if (len <= 0) { uip_abort (); httpd_cleanup (); return; } if (len < uip_mss ()) /* Short read -> EOF */ STATE->eof = 1; STATE->u.vfs.sent = STATE->u.vfs.acked + len; uip_send (uip_appdata, len); }
static void httpd_handle_input(void) { char *ptr = (char *) uip_appdata; #ifdef HTTPD_AUTH_SUPPORT char *start_ptr; if (STATE->header_reparse) { printf("reparse next part of the header\n"); goto start_auth; } #endif /* HTTPD_AUTH_SUPPORT */ if (uip_len < 10) { printf("httpd: received request to short (%d bytes).\n", uip_len); STATE->handler = httpd_handle_400; return; } #ifdef HTTPD_SOAP_SUPPORT if (strncasecmp_P(uip_appdata, PSTR("POST /soap"), 10) == 0) { soap_initialize_context(&STATE->u.soap); STATE->handler = httpd_handle_soap; return; } #endif /* HTTPD_SOAP_SUPPORT */ if (strncasecmp_P(uip_appdata, PSTR("GET /"), 5)) { printf("httpd: received request is not GET.\n"); STATE->handler = httpd_handle_400; return; } char *filename = (char *)uip_appdata + 5; /* beyond slash */ ptr = strchr(filename, ' '); if (ptr == NULL) { printf("httpd: space after filename not found.\n"); STATE->handler = httpd_handle_400; return; } *ptr = 0; /* Terminate filename. */ /* * Successfully parsed the GET request, * possibly check authentication. */ #ifdef HTTPD_AUTH_SUPPORT ptr++; /* Increment pointer to the end of * the GET */ start_auth: start_ptr = ptr; ptr = strstr_P(ptr, PSTR("Authorization: ")); if (ptr == NULL) { if (strstr_P(start_ptr, PSTR("\r\n\r\n"))) { printf("Authorization-header not found.\n"); printf("%s\n", start_ptr); goto auth_failed; } else { ptr = start_ptr; /* Skip all Lines before the last one */ while (1) { ptr = strstr_P(start_ptr, PSTR("\r\n")); if (ptr) start_ptr = ptr + 2; else break; } if (!strncmp(start_ptr, PSTR("Authorization: "), strlen(start_ptr))) { printf("Authorization header is split over two packages, damn"); printf("%s\n", start_ptr); goto auth_failed; } else { STATE->header_reparse = 1; goto after_auth; } } } ptr += 15; /* Skip `Authorization: ' header. */ if (strncmp_P(ptr, PSTR("Basic "), 6)) { printf("auth: method is not basic.\n"); goto auth_failed; } ptr += 6; /* Skip `Basic ' string. */ char *nl = strchr(ptr, '\n'); if (nl == NULL) { printf("auth: newline not found.\n"); goto auth_failed; } *nl = 0; /* Zero-terminate BASE64-string. */ base64_str_decode(ptr); printf("auth: decoded auth string: '%s'.\n", ptr); char *password; if ((password = strchr(ptr, ':')) == NULL) { printf("auth: didn't find colon!\n"); auth_failed: httpd_cleanup(); STATE->handler = httpd_handle_401; STATE->header_reparse = 0; return; } *password = 0; password++; /* Do the PAM authentification */ pam_auth(ptr, password, &STATE->auth_state); if (STATE->header_reparse) { STATE->header_reparse = 0; return; /* We musn't open the file once again */ } after_auth: /* Dummy statement, to keep GCC happy, if HTTP_SD_DIR_SUPPORT is enabled * and thus the uint8_t definition the next statement in code. */ (void) 0; #endif /* HTTPD_AUTH_SUPPORT */ /* * Authentication is okay, now fulfill request for file * refered to in filename. */ #ifndef HTTP_SD_DIR_SUPPORT if (*filename == 0) /* No filename, override -> index */ strcpy_P(filename, PSTR(HTTPD_INDEX)); #endif #ifdef HTTP_FAVICON_SUPPORT if (strcmp_P(filename, PSTR("favicon.ico")) == 0) strcpy_P(filename, PSTR("If.ico")); #endif #ifdef ECMD_PARSER_SUPPORT uint8_t offset = strlen_P(PSTR(ECMD_INDEX "?")); if (strncmp_P(filename, PSTR(ECMD_INDEX "?"), offset) == 0) { httpd_handle_ecmd_setup(filename + offset); return; } #endif /* ECMD_PARSER_SUPPORT */ #ifdef VFS_SUPPORT /* Keep content-type identifing char. */ /* filename instead starts after last directory slash. */ char *slash = strrchr(filename, '/'); if (slash != NULL) { STATE->u.vfs.content_type = *(char *) (slash + 1); } else { STATE->u.vfs.content_type = *filename; } STATE->u.vfs.fd = vfs_open(filename); if (STATE->u.vfs.fd) { STATE->handler = httpd_handle_vfs; return; } /* Now try appending the index.html document name */ ptr = filename + strlen(filename); #ifdef HTTP_SD_DIR_SUPPORT uint8_t lastchar = ptr[-1]; #endif if (ptr[-1] != '/') *(ptr++) = '/'; strcpy_P(ptr, PSTR(HTTPD_INDEX)); STATE->u.vfs.fd = vfs_open(filename); if (STATE->u.vfs.fd) { STATE->handler = httpd_handle_vfs; return; } if (ptr == filename) /* Make sure not to strip initial slash. */ ptr[0] = 0; else ptr[-1] = 0; /* Strip index filename again, * including the last slash. */ #endif /* VFS_SUPPORT */ #ifdef HTTP_SD_DIR_SUPPORT if ((STATE->u.dir.handle = vfs_sd_chdir(filename - 1))) { strncpy(STATE->u.dir.dirname, filename - 1, SD_DIR_MAX_DIRNAME_LEN); STATE->u.dir.dirname[SD_DIR_MAX_DIRNAME_LEN - 1] = 0; if (lastchar != '/') { STATE->handler = httpd_handle_sd_dir_redirect; fat_close_dir(STATE->u.dir.handle); } else STATE->handler = httpd_handle_sd_dir; return; } #endif /* HTTP_SD_DIR_SUPPORT */ /* Fallback, send 404. */ STATE->handler = httpd_handle_404; }