Example #1
0
/*---------------------------------------------------------------------------*/
static
PT_THREAD(handle_script(struct httpd_state *s))
{
  char *ptr;
  
  PT_BEGIN(&s->scriptpt);


  while(s->file.len > 0) {

    /* Check if we should start executing a script. */
    if(*s->file.data == ISO_percent &&
      *(s->file.data + 1) == ISO_bang) {
      s->scriptptr = s->file.data + 3;
      s->scriptlen = s->file.len - 3;
      if(*(s->scriptptr - 1) == ISO_colon) {
	httpd_fs_open(s->scriptptr + 1, &s->file);
	PT_WAIT_THREAD(&s->scriptpt, send_file(s));
      } else {
        // Httpd_cgi is called here
	PT_WAIT_THREAD(&s->scriptpt,
		       httpd_cgi(s->scriptptr)(s, s->scriptptr));
      }
      next_scriptstate(s);
      
      /* The script is over, so we reset the pointers and continue
	 sending the rest of the file. */
      s->file.data = s->scriptptr;
      s->file.len = s->scriptlen;
    } else {
      /* See if we find the start of script marker in the block of HTML
	 to be sent. */

      if(s->file.len > uip_mss()) {
	s->len = uip_mss();
      } else {
	s->len = s->file.len;
      }

      if(*s->file.data == ISO_percent) {
	ptr = strchr(s->file.data + 1, ISO_percent);
      } else {
	ptr = strchr(s->file.data, ISO_percent);
      }
      if(ptr != NULL &&
	 ptr != s->file.data) {
	s->len = (int)(ptr - s->file.data);
	if(s->len >= uip_mss()) {
	  s->len = uip_mss();
	}
      }
      PT_WAIT_THREAD(&s->scriptpt, send_part_of_file(s));
      s->file.data += s->len;
      s->file.len -= s->len;
      
    }
  }
  
  PT_END(&s->scriptpt);
}
Example #2
0
static
PT_THREAD(handle_script(struct httpd_state *s))
{
  /* Note script includes will attach a leading : to the filename and a trailing zero */
  static char scriptname[MAX_SCRIPT_NAME_LENGTH+1],*pptr;
  static uint16_t filelength;

  PT_BEGIN(&s->scriptpt);

  filelength=s->file.len;
  while(s->file.len > 0) {
    /* Sanity check */
    if (s->file.len > filelength) break;

    /* Check if we should start executing a script, flagged by %! */
    if(httpd_fs_getchar(s->file.data) == ISO_percent &&
       httpd_fs_getchar(s->file.data + 1) == ISO_bang) {

       /* Extract name, if starts with colon include file else call cgi */
       s->scriptptr=get_scriptname(scriptname,s->file.data+2);
       s->scriptlen=s->file.len-(s->scriptptr-s->file.data);
       PRINTF("httpd: Handle script named %s\n",scriptname);
       if(scriptname[0] == ISO_colon) {
         if (httpd_fs_open(&scriptname[1], &s->file)) {
           PT_WAIT_THREAD(&s->scriptpt, send_file(s));
         }
       } else {
         PT_WAIT_THREAD(&s->scriptpt,httpd_cgi(scriptname)(s, s->scriptptr));
       }
       next_scriptstate(s);
      
      /* Reset the pointers and continue sending the current file. */
      s->file.data = s->scriptptr;
      s->file.len  = s->scriptlen;
    } else {

     /* Send file up to the next potential script */
      if(s->file.len > uip_mss()) {
        s->len = uip_mss();
      } else {
        s->len = s->file.len;
      }

      if(httpd_fs_getchar(s->file.data) == ISO_percent) {
        pptr = (char *) httpd_fs_strchr(s->file.data + 1, ISO_percent);
      } else {
        pptr = (char *) httpd_fs_strchr(s->file.data, ISO_percent);
      }

      if(pptr != NULL && pptr != s->file.data) {
        s->len = (int)(pptr - s->file.data);
        if(s->len >= uip_mss()) {
          s->len = uip_mss();
        }
      }
      PRINTF("httpd: Sending %u bytes from 0x%04x\n",s->file.len,(unsigned int)s->file.data);
      PT_WAIT_THREAD(&s->scriptpt, send_part_of_file(s));
      s->file.data += s->len;
      s->file.len  -= s->len;
    }
  }

  PT_END(&s->scriptpt);
}
Example #3
0
/*---------------------------------------------------------------------------*/
static
PT_THREAD(handle_script(struct httpd_state *s))
{


  PGM_P ptr;
  
  PT_BEGIN(&s->scriptpt);


  while(s->file.len > 0) {

    /* Check if we should start executing a script. */
    if(pgm_read_byte_near(s->file.data) == ISO_percent &&
       pgm_read_byte_near(s->file.data + 1) == ISO_bang) {
      s->scriptptr = s->file.data + 3;
      s->scriptlen = s->file.len - 3;

      if(pgm_read_byte_near(s->scriptptr - 1) == ISO_colon) {

            strncpy_P(s->tmp_str, s->scriptptr + 1, sizeof(s->tmp_str) -1);
			if(httpd_fs_open(s->tmp_str, &s->file) ||
				httpd_fs_open(s->tmp_str + 1 , &s->file)) {
				PT_WAIT_THREAD(&s->scriptpt, 
           send_file(s));
			} else {
            // could not open the file.
			}

      } else {
            strncpy_P(s->tmp_str, s->scriptptr, sizeof(s->tmp_str) -1);
			((s->tmp_str)[sizeof(s->tmp_str) - 1]) = '\0';
					PT_WAIT_THREAD(&s->scriptpt, 
           httpd_cgi(s->tmp_str)(s, s->tmp_str));
      }
      next_scriptstate(s);
      
      /* The script is over, so we reset the pointers and continue
    	 sending the rest of the file. */
      s->file.data = s->scriptptr;
      s->file.len = s->scriptlen;
    } else {
      /* See if we find the start of script marker in the block of HTML
	        to be sent. */

      if(s->file.len > uip_mss()) {
	      s->len = uip_mss();
      } else {
	      s->len = s->file.len;
      }

      if(pgm_read_byte_near(s->file.data) == ISO_percent) {
	      ptr = strchr_P(s->file.data + 1, ISO_percent);

      } else {
	      ptr = strchr_P(s->file.data, ISO_percent);

      }

      if(ptr != NULL &&
      	 ptr != s->file.data) {
        	s->len = (int)(ptr - s->file.data);
        	if(s->len >= uip_mss()) {
        	  s->len = uip_mss();
      	}
      }

      PT_WAIT_THREAD(&s->scriptpt, send_part_of_file(s));

      s->file.data += s->len;
      s->file.len -= s->len;
      
    }
  }
  
  PT_END(&s->scriptpt);


	/*
  PGM_P ptr;
  
  PT_BEGIN(&s->scriptpt);

  while(s->file.len > 0) {
    // Check if we should start executing a script.
    if( (pgm_read_byte(s->file.data) == ISO_percent) &&
        (pgm_read_byte(s->file.data + 1) == ISO_bang)) {
      s->scriptptr = s->file.data + 3;
      s->scriptlen = s->file.len - 3;

      if(pgm_read_byte(s->scriptptr - 1) == ISO_colon) {
          strncpy_P(s->tmp_str, s->scriptptr + 1, sizeof(s->tmp_str) -1);
        if (httpd_fs_open(s->tmp_str, &s->file))
        {
	        PT_WAIT_THREAD(&s->scriptpt, send_file(s));
        }
      } else {
	    PT_WAIT_THREAD(&s->scriptpt,
		       httpd_cgi(s->scriptptr)(s, s->scriptptr));
      }

      next_scriptstate(s);
      
      // The script is over, so we reset the pointers and continue
	  // sending the rest of the file.
      s->file.data = s->scriptptr;
      s->file.len = s->scriptlen;
    } else {
      // See if we find the start of script marker in the block of HTML
	  //   to be sent. 

      if(s->file.len > uip_mss()) {
        s->len = uip_mss();
      } else {
        s->len = s->file.len;
      }

      if(pgm_read_byte(s->file.data) == ISO_percent) {
        ptr = strchr_P(s->file.data + 1, ISO_percent);
      } else {
        ptr = strchr_P(s->file.data, ISO_percent);
      }

      if(ptr != NULL &&
	     ptr != s->file.data) {
        s->len = (int)(ptr - s->file.data);

        if(s->len >= uip_mss()) {
            s->len = uip_mss();
        }
      }

      PT_WAIT_THREAD(&s->scriptpt, send_part_of_file(s));
      s->file.data += s->len;
      s->file.len -= s->len;
    }
  }
  
  PT_END(&s->scriptpt);
  */
}
Example #4
0
/*-----------------------------------------------------------------------------------*/
void
httpd_appcall(void)
{
  struct fs_file fsfile;

  u8_t i;

  switch(uip_conn->lport) {
    /* This is the web server: */
  case HTONS(httpPORT):
    /* Pick out the application state from the uip_conn structure. */
    hs = (struct httpd_state *)(uip_conn->appstate);

    /* We use the uip_ test functions to deduce why we were
       called. If uip_connected() is non-zero, we were called
       because a remote host has connected to us. If
       uip_newdata() is non-zero, we were called because the
       remote host has sent us new data, and if uip_acked() is
       non-zero, the remote host has acknowledged the data we
       previously sent to it. */
    if(uip_connected()) {
      /* Since we have just been connected with the remote host, we
         reset the state for this connection. The ->count variable
         contains the amount of data that is yet to be sent to the
         remote host, and the ->state is set to HTTP_NOGET to signal
         that we haven't received any HTTP GET request for this
         connection yet. */

      hs->state = HTTP_NOGET;
      hs->count = 0;
      return;

    } else if(uip_poll()) {
      /* If we are polled ten times, we abort the connection. This is
         because we don't want connections lingering indefinately in
         the system. */
      if(hs->count++ >= 10) {
	uip_abort();
      }
      return;
    } else if(uip_newdata() && hs->state == HTTP_NOGET) {
      /* This is the first data we receive, and it should contain a
	 GET. */

      /* Check for GET. */
      if(uip_appdata[0] != ISO_G ||
	 uip_appdata[1] != ISO_E ||
	 uip_appdata[2] != ISO_T ||
	 uip_appdata[3] != ISO_space) {
	/* If it isn't a GET, we abort the connection. */
	uip_abort();
	return;
      }
	
      /* Find the file we are looking for. */
      for(i = 4; i < 40; ++i) {
	if(uip_appdata[i] == ISO_space ||
	   uip_appdata[i] == ISO_cr ||
	   uip_appdata[i] == ISO_nl) {
	  uip_appdata[i] = 0;
	  break;
	}
      }

      PRINT("request for file ");
      PRINTLN(&uip_appdata[4]);

      /* Check for a request for "/". */
      if(uip_appdata[4] == ISO_slash &&
	 uip_appdata[5] == 0) {
	fs_open(file_index_html.name, &fsfile);
      } else {
	if(!fs_open((const char *)&uip_appdata[4], &fsfile)) {
	  PRINTLN("couldn't open file");
	  fs_open(file_404_html.name, &fsfile);
	}
      }


      if(uip_appdata[4] == ISO_slash &&
	 uip_appdata[5] == ISO_c &&
	 uip_appdata[6] == ISO_g &&
	 uip_appdata[7] == ISO_i &&
	 uip_appdata[8] == ISO_slash) {
	/* If the request is for a file that starts with "/cgi/", we
           prepare for invoking a script. */	
	hs->script = fsfile.data;
	next_scriptstate();
      } else {
	hs->script = NULL;
	/* The web server is now no longer in the HTTP_NOGET state, but
	   in the HTTP_FILE state since is has now got the GET from
	   the client and will start transmitting the file. */
	hs->state = HTTP_FILE;

	/* Point the file pointers in the connection state to point to
	   the first byte of the file. */
	hs->dataptr = fsfile.data;
	hs->count = fsfile.len;	
      }
    }


    if(hs->state != HTTP_FUNC) {
      /* Check if the client (remote end) has acknowledged any data that
	 we've previously sent. If so, we move the file pointer further
	 into the file and send back more data. If we are out of data to
	 send, we close the connection. */
      if(uip_acked()) {
	if(hs->count >= uip_conn->len) {
	  hs->count -= uip_conn->len;
	  hs->dataptr += uip_conn->len;
	} else {
	  hs->count = 0;
	}
	
	if(hs->count == 0) {
	  if(hs->script != NULL) {
	    next_scriptline();
	    next_scriptstate();
	  } else {
	    uip_close();
	  }
	}
      }
    } else {
      /* Call the CGI function. */
      if(cgitab[hs->script[2] - ISO_a](uip_acked())) {
	/* If the function returns non-zero, we jump to the next line
           in the script. */
	next_scriptline();
	next_scriptstate();
      }
    }

    if(hs->state != HTTP_FUNC && !uip_poll()) {
      /* Send a piece of data, but not more than the MSS of the
	 connection. */
      uip_send(( void * ) hs->dataptr, hs->count);
    }

    /* Finally, return to uIP. Our outgoing packet will soon be on its
       way... */
    return;

  default:
    /* Should never happen. */
    uip_abort();
    break;
  }
}
Example #5
0
/*-----------------------------------------------------------------------------------*/
DISPATCHER_UIPCALL(httpd_appcall, state)
{
  struct httpd_fs_file fsfile;  
  u8_t i;
  DISPATCHER_UIPCALL_ARG(state);

  hs = (struct httpd_state *)(state);
  
  /* We use the uip_ test functions to deduce why we were
     called. If uip_connected() is non-zero, we were called
     because a remote host has connected to us. If
     uip_newdata() is non-zero, we were called because the
     remote host has sent us new data, and if uip_acked() is
     non-zero, the remote host has acknowledged the data we
     previously sent to it. */
  if(uip_connected()) {

    /* Since we've just been connected, the state pointer should be
       NULL and we need to allocate a new state object. If we have run
       out of memory for state objects, we'll have to abort the
       connection and return. */
    if(hs == NULL) {
      hs = alloc_state();
      if(hs == NULL) {
	uip_close();
	return;
      }
      dispatcher_markconn(uip_conn, (void *)hs);
    }
    /* Since we have just been connected with the remote host, we
       reset the state for this connection. The ->count variable
       contains the amount of data that is yet to be sent to the
       remote host, and the ->state is set to HTTP_NOGET to signal
       that we haven't received any HTTP GET request for this
       connection yet. */
    hs->state = HTTP_NOGET;
    hs->count = 0;
    hs->poll = 0;
  } else if(uip_closed() || uip_aborted()) {
    if(hs != NULL) {
      dealloc_state(hs);
    }
    return;
  } else if(uip_poll()) {
    /* If we are polled ten times, we abort the connection. This is
       because we don't want connections lingering indefinately in
       the system. */
    if(hs != NULL) {
      if(hs->state == HTTP_DEALLOCATED) {
	uip_abort();
      } else if(hs->poll++ >= 100) {
	uip_abort();
	dealloc_state(hs);
      }
    }
    return;
  }


  if(uip_newdata() && hs->state == HTTP_NOGET) {
    hs->poll = 0;
    /* This is the first data we receive, and it should contain a
       GET. */
      
    /* Check for GET. */
    if(uip_appdata[0] != ISO_G ||
       uip_appdata[1] != ISO_E ||
       uip_appdata[2] != ISO_T ||
       uip_appdata[3] != ISO_space) {
      /* If it isn't a GET, we abort the connection. */
      uip_abort();
      dealloc_state(hs);
      return;
    }

    beep();
    
    /* Find the file we are looking for. */
    for(i = 4; i < 40; ++i) {
      if(uip_appdata[i] == ISO_space ||
	 uip_appdata[i] == ISO_cr ||
	 uip_appdata[i] == ISO_nl) {
	uip_appdata[i] = 0;
	break;
      }
    }

    PRINT("request for file ");
    PRINTLN(&uip_appdata[4]);
    webserver_log_file(uip_conn->ripaddr, &uip_appdata[4]);
    /* Check for a request for "/". */
    if(uip_appdata[4] == ISO_slash &&
       uip_appdata[5] == 0) {
      httpd_fs_open(file_index_html.name, &fsfile);    
    } else {
      if(!httpd_fs_open((const char *)&uip_appdata[4], &fsfile)) {
	PRINTLN("couldn't open file");
	httpd_fs_open(file_404_html.name, &fsfile);
      }
    } 

    if(uip_appdata[4] == ISO_slash &&
       uip_appdata[5] == ISO_c &&
       uip_appdata[6] == ISO_g &&
       uip_appdata[7] == ISO_i &&
       uip_appdata[8] == ISO_slash) {
      /* If the request is for a file that starts with "/cgi/", we
	 prepare for invoking a script. */	
      hs->script = fsfile.data;
      next_scriptstate();
    } else {
      hs->script = NULL;
      /* The web server is now no longer in the HTTP_NOGET state, but
	 in the HTTP_FILE state since is has now got the GET from
	 the client and will start transmitting the file. */
      hs->state = HTTP_FILE;

      /* Point the file pointers in the connection state to point to
	 the first byte of the file. */
      hs->dataptr = fsfile.data;
      hs->count = fsfile.len;	
    }     
  }

    
  if(hs->state != HTTP_FUNC) {
    /* Check if the client (remote end) has acknowledged any data that
       we've previously sent. If so, we move the file pointer further
       into the file and send back more data. If we are out of data to
       send, we close the connection. */
    if(uip_acked()) {
      hs->poll = 0;	
      if(hs->count >= uip_mss()) {
	hs->count -= uip_mss();
	hs->dataptr += uip_mss();
      } else {
	hs->count = 0;
      }
	
      if(hs->count == 0) {
	if(hs->script != NULL) {
	  next_scriptline();
	  next_scriptstate();
	} else {
	  uip_close();
	  dealloc_state(hs);
	}
      }
    }         
  }
    
  if(hs->state == HTTP_FUNC) {
    /* Call the CGI function. */
#if 1
    if(httpd_cgitab[hs->script[2] - ISO_a]()) {
      /* If the function returns non-zero, we jump to the next line
	 in the script. */
      next_scriptline();
      next_scriptstate();
    }
#endif
  }

  if(hs->state != HTTP_FUNC && !uip_poll()) {
    hs->poll = 0;
    /* Send a piece of data, but not more than the MSS of the
       connection. */
    uip_send(hs->dataptr,
	     hs->count > uip_mss()? uip_mss(): hs->count);
  }

  /* Finally, return to uIP. Our outgoing packet will soon be on its
     way... */
}