//This is the implementation of the UIPAPP that uIP will call when
//something network data related happens.
//The purpose of this app is to move buffer data to and from the network
void uip_socket_app(void)
{
    int i;
    file_handle_t file_handle =  (uip_conn->appstate)[0];
    struct file_t* file = NULL;
    struct buffer_t *rxbuf = NULL;
    struct buffer_t *txbuf = NULL;
    bool may_send = true;

#ifdef __DEBUG
    printf("\r\napp: process conn @ %p", uip_conn);
#endif


    if(uip_connected())
    {
#ifdef __DEBUG
        printf("\r\napp: connected. Ports %hd:%hd", uip_conn->lport, uip_conn->rport);
#endif
        if( file_handle == FILE_INVALID_HANDLE )
        {
            //it's an incoming connection (no assigned handle)
            //find the index of the listening port
            for( i = 0; i < UIP_LISTENPORTS ; i++ )
            {
                if( uip_listenports[i] == uip_conn->lport )
                {
                    file_handle = listenports[i](uip_conn->lport, uip_conn->ripaddr, uip_conn->rport);
                    if( file_handle != FILE_INVALID_HANDLE )
                    {
                        uip_conn->appstate[0] = file_handle;
                    }
                    break;
                }
            }
        }
    }
    if( file_handle == FILE_INVALID_HANDLE)
    {
        goto close_or_abort;
    }

    file =  file_get_by_handle(file_handle);
    rxbuf = file->read_buffer;
    txbuf = file->write_buffer;


    if( file->state == ClosePending )
    {
#ifdef __DEBUG
        printf("\r\napp: freeing handle %hhd",uip_conn->appstate[0]);
#endif
        file_free(uip_conn->appstate[0]);
        uip_conn->appstate[0] = FILE_INVALID_HANDLE;
        goto close_or_abort;
    }


    if( rxbuf == NULL || txbuf == NULL )
    {
        goto close_or_abort;
    }

    if( uip_connected() ) file->state = Open;

    if( uip_acked() ) {
#ifdef __DEBUG
        printf("\r\napp: acked %d bytes", uip_this_ack);
#endif
        buffer_seek( txbuf, uip_this_ack );
    }

    int free = buffer_free( rxbuf );//free to write to
    int available = buffer_available( txbuf );//available to read

    if(uip_rexmit()) {
//#ifdef __DEBUG
        printf("\r\napp: rexmit. Handle: %hhd", file_handle);
//#endif
        buffer_peek( txbuf, (char*)uip_appdata, uip_conn->len);
        uip_send(uip_appdata, uip_conn->len);
        may_send = false;
    }
    else if(uip_newdata())
    {
#ifdef __DEBUG
        printf("\r\napp: newdata. Handle: %hhd. len=%u\n", file_handle, uip_datalen() );
#endif
        if( free >= uip_datalen() )
        {
            free -= buffer_write( rxbuf, (char*)uip_appdata, uip_datalen() );
        }
        else {
            puts("buffer overflow\n");
        }
    }
    else if( uip_closed() )
    {
#ifdef __DEBUG
        printf("\r\napp: connection id %hhd closed\n", file_handle );
#endif
        file->state = Closed;
        may_send = false;
    }
    else if( uip_aborted() )
    {
#ifdef __DEBUG
        printf("\r\napp: connection id %hhd aborted\n", file_handle );
#endif
        file->state = Aborted;
        may_send = false;
    }
    else if( uip_timedout() )
    {
#ifdef __DEBUG
        printf("\r\napp: connection id %hhd timed out\n", file_handle );
#endif
        file->state = TimedOut;
        may_send = false;
    }
//	if( available >  0 && file->state > Open )
//	{
//		buffer_seek( txbuf, available);
//	}
    if( available > 0 && may_send && uip_conn->len == 0) {
        //we can send the smaller of what's available or the connection mss
        int size = available < uip_mss() ? available : uip_mss() ;
        int peek = buffer_peek( txbuf, (char*)uip_appdata, size);
        uip_appdata[peek] = '\0';
#ifdef __DEBUG
        printf("\r\napp: sending %d of %d available bytes: [%s] ", peek,available, (char*)uip_appdata);
#endif
        uip_send(uip_appdata, peek);

    }
    /*
    This code prevents the "silly-window" TCP problem
    The problem is though, that we want to fill our rx buffer entirely
    sometimes before acting on it.
    I've disabled this code in the meantime, until we can
    set the behaviour on a connection basis
    ...Or it becomes apparent that we just don't need it.

    if( free < rxbuf->size / 2 )
    {
    	puts("\napp: stopping rx\n");
    	uip_stop();
    }
    else if( uip_stopped(uip_conn) )
    {
    	puts("\napp: restarting rx\n");
    	uip_restart(); //TODO NEED to be able to set the window size?
    }
    */
    //...instead let's try setting the window size
    uip_receive_window = free;
    return;

close_or_abort:
    if( uip_closed() || uip_aborted() || uip_timedout() )
    {
        puts("\r\napp: abort chosen");
        uip_abort();
    }
    else
    {
        puts("\r\napp: close chosen");
        uip_close();
    }

}
示例#2
0
文件: httpd.c 项目: jaseg/avr-uip
/*---------------------------------------------------------------------------*/
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);
  */
}
示例#3
0
static uint16_t send_interrupt(FAR struct uip_driver_s *dev, FAR void *pvconn,
                               FAR void *pvpriv, uint16_t flags)
{
  FAR struct uip_conn *conn = (FAR struct uip_conn*)pvconn;
  FAR struct socket *psock = (FAR struct socket *)pvpriv;

  nllvdbg("flags: %04x\n", flags);

  /* If this packet contains an acknowledgement, then update the count of
   * acknowledged bytes.
   */

  if ((flags & UIP_ACKDATA) != 0)
    {
      FAR sq_entry_t *entry, *next;
      FAR struct uip_wrbuffer_s *segment;
      uint32_t ackno;

      ackno = uip_tcpgetsequence(TCPBUF->ackno);
      for (entry = sq_peek(&conn->unacked_q); entry; entry = next)
        {
          next    = sq_next(entry);
          segment = (FAR struct uip_wrbuffer_s*)entry;

          if (segment->wb_seqno < ackno)
            {
              nllvdbg("ACK: acked=%d buflen=%d ackno=%d\n",
                      segment->wb_seqno, segment->wb_nbytes, ackno);

              /* Segment was ACKed. Remove from ACK waiting queue */

              sq_rem(entry, &conn->unacked_q);

              /* Return the write buffer to the pool of free buffers */

              uip_tcpwrbuffer_release(segment);
            }
        }
    }

  /* Check for a loss of connection */

  else if ((flags & (UIP_CLOSE | UIP_ABORT | UIP_TIMEDOUT)) != 0)
    {
      /* Report not connected */

       nllvdbg("Lost connection\n");
       net_lostconnection(psock, flags);
       goto end_wait;
     }

   /* Check if we are being asked to retransmit data */

   else if ((flags & UIP_REXMIT) != 0)
    {
      sq_entry_t *entry;

      /* Put all segments that have been sent but not ACKed to write queue
       * again note, the un-ACKed segment is put at the first of the write_q,
       * so it can be sent as soon as possible.
       */

      while ((entry = sq_remlast(&conn->unacked_q)))
        {
          struct uip_wrbuffer_s *segment = (struct uip_wrbuffer_s*)entry;

          if (segment->wb_nrtx >= UIP_MAXRTX)
            {
              //conn->unacked -= segment->wb_nbytes;

              /* Return the write buffer */

              uip_tcpwrbuffer_release(segment);

              /* NOTE expired is different from un-ACKed, it is designed to
               * represent the number of segments that have been sent,
               * retransmitted, and un-ACKed, if expired is not zero, the
               * connection will be closed.
               *
               * field expired can only be updated at UIP_ESTABLISHED state
               */

              conn->expired++;
              continue;
            }

          send_insert_seqment(segment, &conn->write_q);
        }
    }

  /* Check if the outgoing packet is available (it may have been claimed
   * by a sendto interrupt serving a different thread).
   */

  if (dev->d_sndlen > 0)
    {
      /* Another thread has beat us sending data, wait for the next poll */

      return flags;
    }

  /* We get here if (1) not all of the data has been ACKed, (2) we have been
   * asked to retransmit data, (3) the connection is still healthy, and (4)
   * the outgoing packet is available for our use.  In this case, we are
   * now free to send more data to receiver -- UNLESS the buffer contains
   * unprocesed incoming data.  In that event, we will have to wait for the
   * next polling cycle.
   */

  if ((conn->tcpstateflags & UIP_ESTABLISHED) &&
      (flags & (UIP_POLL | UIP_REXMIT)) &&
      !(sq_empty(&conn->write_q)))
    {
      /* Check if the destination IP address is in the ARP table.  If not,
       * then the send won't actually make it out... it will be replaced with
       * an ARP request.
       *
       * NOTE 1: This could be an expensive check if there are a lot of
       * entries in the ARP table.
       *
       * NOTE 2: If we are actually harvesting IP addresses on incomming IP
       * packets, then this check should not be necessary; the MAC mapping
       * should already be in the ARP table.
       */

#if defined(CONFIG_NET_ETHERNET) && !defined(CONFIG_NET_ARP_IPIN)
      if (uip_arp_find(conn->ripaddr) != NULL)
#endif
        {
          FAR struct uip_wrbuffer_s *segment;
          FAR void *sndbuf;
          size_t sndlen;

          /* Get the amount of data that we can send in the next packet */

          segment = (FAR struct uip_wrbuffer_s *)sq_remfirst(&conn->write_q);
          if (segment)
            {
              sndbuf = segment->wb_buffer;
              sndlen = segment->wb_nbytes;

              DEBUGASSERT(sndlen <= uip_mss(conn));

              /* REVISIT:  There should be a check here to assure that we do
               * not excced the window (conn->winsize).
               */

              /* Set the sequence number for this segment.  NOTE: uIP
               * updates sndseq on receipt of ACK *before* this function
               * is called. In that case sndseq will point to the next
               * unacknowledged byte (which might have already been
               * sent). We will overwrite the value of sndseq here
               * before the packet is sent.
               */

              if (segment->wb_nrtx == 0 && segment->wb_seqno == (unsigned)-1)
                {
                  segment->wb_seqno = conn->isn + conn->sent;
                }

              uip_tcpsetsequence(conn->sndseq, segment->wb_seqno);

              /* Then set-up to send that amount of data. (this won't
               * actually happen until the polling cycle completes).
               */

              uip_send(dev, sndbuf, sndlen);

              /* Remember how much data we send out now so that we know
               * when everything has been acknowledged.  Just increment
               * the amount of data sent. This will be needed in
               * sequence* number calculations and we know that this is
               * not a re-transmission. Re-transmissions do not go through
               * this path.
               */

              if (segment->wb_nrtx == 0)
                {
                  conn->unacked += sndlen;
                  conn->sent    += sndlen;
                }

              /* Increment the retransmission counter before expiration.
               * NOTE we will not calculate the retransmission timer
               * (RTT) to save cpu cycles, each send_insert_seqment
               * segment will be retransmitted UIP_MAXRTX times in halt-
               * second interval before expiration.
               */

              segment->wb_nrtx++;

              /* The segment is waiting for ACK again */

              send_insert_seqment(segment, &conn->unacked_q);

              /* Only one data can be sent by low level driver at once,
               * tell the caller stop polling the other connection.
               */

              flags &= ~UIP_POLL;
            }
        }
    }

  /* Continue waiting */

  return flags;

end_wait:

  /* Do not allow any further callbacks */

  psock->s_sndcb->flags = 0;
  psock->s_sndcb->event = NULL;

  return flags;
}
示例#4
0
文件: httpd-cgi.c 项目: ADVANSEE/mist
/*---------------------------------------------------------------------------*/
static unsigned short
make_route(void *p)
{
  static const char httpd_cgi_rtesh[] HTTPD_STRING_ATTR = " ";
  static const char httpd_cgi_rtes0[] HTTPD_STRING_ATTR = "<tr><td>";
  static const char httpd_cgi_rtes1[] HTTPD_STRING_ATTR = "</td><td>%u</td><td>";
  static const char httpd_cgi_rtes2[] HTTPD_STRING_ATTR = ", %lu s";
  uint16_t numprinted;
  struct httpd_state *s = (struct httpd_state *)p;
  uip_ds6_route_t *r;

  //  conn = &uip_conns[s->u.count];

  numprinted =
    httpd_snprintf((char *)uip_appdata, uip_mss(), httpd_cgi_rtesh);
  if(numprinted >= uip_mss()) {
    return write_mss_error(11);
  }
  {
    r = s->u.ptr;

    /* <tr><td> */
    numprinted += httpd_snprintf((char *)uip_appdata + numprinted,
				 uip_mss() - numprinted,
				 httpd_cgi_rtes0);
    if(numprinted >= uip_mss()) {
      return write_mss_error(12);
    }
    numprinted += httpd_cgi_sprint_ip6(&r->ipaddr,
				       (char *)uip_appdata + numprinted);
    if(numprinted >= uip_mss()) {
      return write_mss_error(13);
    }

    uip_ds6_nbr_t *n;
    uip_ipaddr_t *nexthop;
    int nopath = 0;

    nexthop = uip_ds6_route_nexthop(r);
    n = uip_ds6_nbr_lookup(nexthop);
    if(r != NULL) {
      nopath = r->state.nopath_received;
    }
    numprinted += httpd_snprintf((char *)uip_appdata + numprinted,
				 uip_mss() - numprinted,
				 httpd_cgi_rtes1,
				 nopath);
    if(numprinted >= uip_mss()) {
      return write_mss_error(14);
    }
    if(nexthop != NULL) {
      numprinted += httpd_cgi_sprint_ip6(nexthop,
                                         (char *)uip_appdata + numprinted);
    }
    if(numprinted >= uip_mss()) {
      return write_mss_error(15);
    }
    if(r->state.lifetime < 3600L * 24) {
      numprinted += httpd_snprintf((char *)uip_appdata + numprinted,
                                   uip_mss() - numprinted,
                                   httpd_cgi_rtes2,
                                   r->state.lifetime);
      if(numprinted >= uip_mss()) {
        return write_mss_error(16);
      }
    }

    /* Ping */
    if(simple_udp_ping_has_reply(&r->ipaddr)) {
      int delay = simple_udp_ping_get_delay(&r->ipaddr);
      numprinted +=
          httpd_snprintf((char *)uip_appdata + numprinted,
                         uip_mss() - numprinted, "</td><td>%u ms", delay);
      if(numprinted >= uip_mss()) {
        return write_mss_error(6);
      }
    } else if(simple_udp_ping_has_sent(&r->ipaddr)) {
      numprinted +=
          httpd_snprintf((char *)uip_appdata + numprinted,
                         uip_mss() - numprinted, "</td><td>Ping scheduled...");
      if(numprinted >= uip_mss()) {
        return write_mss_error(7);
      }
    } else {
      numprinted +=
          httpd_snprintf((char *)uip_appdata + numprinted,
                         uip_mss() - numprinted, "</td><td>-");
      if(numprinted >= uip_mss()) {
        return write_mss_error(8);
      }
    }

    numprinted +=
        httpd_snprintf((char *)uip_appdata + numprinted,
                       uip_mss() - numprinted, httpd_cgi_addrb);
    if(numprinted >= uip_mss()) {
      return write_mss_error(9);
    }


  }
  return numprinted;
}
示例#5
0
文件: httpd.c 项目: alemv/u-boot
// called for http server app
void httpd_appcall(void){
	struct fs_file fsfile;
	unsigned int i;

	switch(uip_conn->lport){

		case HTONS(80):

			// app state
			hs = (struct httpd_state *)(uip_conn->appstate);

			// closed connection
			if(uip_closed()){
				httpd_state_reset();
				uip_close();
				return;
			}

			// aborted connection or time out occured
			if(uip_aborted() || uip_timedout()){
				httpd_state_reset();
				uip_abort();
				return;
			}

			// if we are pooled
			if(uip_poll()){
				if(hs->count++ >= 100){
					httpd_state_reset();
					uip_abort();
				}
				return;
			}

			// new connection
			if(uip_connected()){
				httpd_state_reset();
				return;
			}

			// new data in STATE_NONE
			if(uip_newdata() && hs->state == STATE_NONE){

				// GET or POST request?
				if(uip_appdata[0] == ISO_G && uip_appdata[1] == ISO_E && uip_appdata[2] == ISO_T && (uip_appdata[3] == ISO_space || uip_appdata[3] == ISO_tab)){
					hs->state = STATE_FILE_REQUEST;
				} else if(uip_appdata[0] == ISO_P && uip_appdata[1] == ISO_O && uip_appdata[2] == ISO_S && uip_appdata[3] == ISO_T && (uip_appdata[4] == ISO_space || uip_appdata[4] == ISO_tab)){
					hs->state = STATE_UPLOAD_REQUEST;
				}

				// anything else -> abort the connection!
				if(hs->state == STATE_NONE){
					httpd_state_reset();
					uip_abort();
					return;
				}

				// get file or firmware upload?
				if(hs->state == STATE_FILE_REQUEST){

					// we are looking for GET file name
					for(i = 4; i < 30; i++){
						if(uip_appdata[i] == ISO_space || uip_appdata[i] == ISO_cr || uip_appdata[i] == ISO_nl || uip_appdata[i] == ISO_tab){
							uip_appdata[i] = 0;
							i = 0;
							break;
						}
					}

					if(i != 0){
						printf("## Error: request file name too long!\n");
						httpd_state_reset();
						uip_abort();
						return;
					}

					printf("Request for: ");
					printf("%s\n", &uip_appdata[4]);

					// request for /
					if(uip_appdata[4] == ISO_slash && uip_appdata[5] == 0){
						fs_open(file_index_html.name, &fsfile);
					} else {
						// check if we have requested file
						if(!fs_open((const char *)&uip_appdata[4], &fsfile)){
							printf("## Error: file not found!\n");
							fs_open(file_404_html.name, &fsfile);
						}
					}

					hs->state = STATE_FILE_REQUEST;
					hs->dataptr = (u8_t *)fsfile.data;
					hs->upload = fsfile.len;

					// send first (and maybe the last) chunk of data
					uip_send(hs->dataptr, (hs->upload > uip_mss() ? uip_mss() : hs->upload));
					return;

				} else if(hs->state == STATE_UPLOAD_REQUEST){

					char *start = NULL;
					char *end = NULL;

					// end bufor data with NULL
					uip_appdata[uip_len] = '\0';

					/*
					 * We got first packet with POST request
					 *
					 * Some browsers don't include first chunk of data in the first
					 * POST request packet (like Google Chrome, IE and Safari)!
					 * So we must now find two values:
					 * - Content-Length
					 * - boundary
					 * Headers with these values can be in any order!
					 * If we don't find these values in first packet, connection will be aborted!
					 *
					 */

					// Content-Length pos
					start = (char *)strstr((char*)uip_appdata, "Content-Length:");

					if(start){

						start += sizeof("Content-Length:");

						// find end of the line with "Content-Length:"
						end = (char *)strstr(start, eol);

						if(end){

							hs->upload_total = atoi(start);
#ifdef DEBUG_UIP
							printf("Expecting %d bytes in body request message\n", hs->upload_total);
#endif

						} else {
							printf("## Error: couldn't find \"Content-Length\"!\n");
							httpd_state_reset();
							uip_abort();
							return;
						}

					} else {
						printf("## Error: couldn't find \"Content-Length\"!\n");
						httpd_state_reset();
						uip_abort();
						return;
					}

					// we don't support very small files (< 10 KB)
					if(hs->upload_total < 10240){
						printf("## Error: request for upload < 10 KB data!\n");
						httpd_state_reset();
						uip_abort();
						return;
					}

					// boundary value
					start = NULL;
					end = NULL;

					start = (char *)strstr((char *)uip_appdata, "boundary=");

					if(start){

						// move pointer over "boundary="
						start += 9;

						// find end of line with boundary value
						end = (char *)strstr((char *)start, eol);

						if(end){

							// malloc space for boundary value + '--' and '\0'
							boundary_value = (char*)malloc(end - start + 3);

							if(boundary_value){

								memcpy(&boundary_value[2], start, end - start);

								// add -- at the begin and 0 at the end
								boundary_value[0] = '-';
								boundary_value[1] = '-';
								boundary_value[end - start + 2] = 0;

#ifdef DEBUG_UIP
								printf("Found boundary value: \"%s\"\n", boundary_value);
#endif

							} else {
								printf("## Error: couldn't allocate memory for boundary!\n");
								httpd_state_reset();
								uip_abort();
								return;
							}

						} else {
							printf("## Error: couldn't find boundary!\n");
							httpd_state_reset();
							uip_abort();
							return;
						}

					} else {
						printf("## Error: couldn't find boundary!\n");
						httpd_state_reset();
						uip_abort();
						return;
					}

					/*
					 * OK, if we are here, it means that we found
					 * Content-Length and boundary values in headers
					 *
					 * We can now try to 'allocate memory' and
					 * find beginning of the data in first packet
					 */

					webfailsafe_data_pointer = (u8_t *)WEBFAILSAFE_UPLOAD_RAM_ADDRESS;

					if(!webfailsafe_data_pointer){
						printf("## Error: couldn't allocate RAM for data!\n");
						httpd_state_reset();
						uip_abort();
						return;
					} else {
						printf("Data will be downloaded at 0x%X in RAM\n", WEBFAILSAFE_UPLOAD_RAM_ADDRESS);
					}

					if(httpd_findandstore_firstchunk()){
						data_start_found = 1;
					} else {
						data_start_found = 0;
					}

					return;

				} /* else if(hs->state == STATE_UPLOAD_REQUEST) */

			} /* uip_newdata() && hs->state == STATE_NONE */

			// if we got ACK from remote host
			if(uip_acked()){

				// if we are in STATE_FILE_REQUEST state
				if(hs->state == STATE_FILE_REQUEST){

					// data which we send last time was received (we got ACK)
					// if we send everything last time -> gently close the connection
					if(hs->upload <= uip_mss()){

						// post upload completed?
						if(webfailsafe_post_done){

							if(!webfailsafe_upload_failed){
								webfailsafe_ready_for_upgrade = 1;
							}

							webfailsafe_post_done = 0;
							webfailsafe_upload_failed = 0;
						}

						httpd_state_reset();
						uip_close();
						return;
					}

					// otherwise, send another chunk of data
					// last time we sent uip_conn->len size of data
					hs->dataptr += uip_conn->len;
					hs->upload -= uip_conn->len;

					uip_send(hs->dataptr, (hs->upload > uip_mss() ? uip_mss() : hs->upload));
				}

				return;

			}

			// if we need to retransmit
			if(uip_rexmit()){

				// if we are in STATE_FILE_REQUEST state
				if(hs->state == STATE_FILE_REQUEST){
					// send again chunk of data without changing pointer and length of data left to send
					uip_send(hs->dataptr, (hs->upload > uip_mss() ? uip_mss() : hs->upload));
				}

				return;

			}

			// if we got new data frome remote host
			if(uip_newdata()){

				// if we are in STATE_UPLOAD_REQUEST state
				if(hs->state == STATE_UPLOAD_REQUEST){

					// end bufor data with NULL
					uip_appdata[uip_len] = '\0';

					// do we have to find start of data?
					if(!data_start_found){

						if(!httpd_findandstore_firstchunk()){
							printf("## Error: couldn't find start of data in next packet!\n");
							httpd_state_reset();
							uip_abort();
							return;
						} else {
							data_start_found = 1;
						}

						return;
					}

					hs->upload += (unsigned int)uip_len;

					if(!webfailsafe_upload_failed){
						memcpy((void *)webfailsafe_data_pointer, (void *)uip_appdata, uip_len);
						webfailsafe_data_pointer += uip_len;
					}

					httpd_download_progress();

					// if we have collected all data
					if(hs->upload >= hs->upload_total){

						printf("\n\n");

						// end of post upload
						webfailsafe_post_done = 1;
						NetBootFileXferSize = (ulong)hs->upload_total;

						// which website will be returned
						if(!webfailsafe_upload_failed){
							fs_open(file_flashing_html.name, &fsfile);
						} else {
							fs_open(file_fail_html.name, &fsfile);
						}

						httpd_state_reset();

						hs->state = STATE_FILE_REQUEST;
						hs->dataptr = (u8_t *)fsfile.data;
						hs->upload = fsfile.len;

						uip_send(hs->dataptr, (hs->upload > uip_mss() ? uip_mss() : hs->upload));
					}

				}

				return;
			}

			break;

		default:
			// we shouldn't get here... we are listening only on port 80
			uip_abort();
			break;
	}
}
示例#6
0
/*---------------------------------------------------------------------------*/
static unsigned short
generate_file_stats(void *arg)
{
  char *f = (char *)arg;
  return snprintf((char *)uip_appdata, uip_mss(), "%5u", httpd_fs_count(f));
}
示例#7
0
/*---------------------------------------------------------------------------*/
static void
appcall(void *state)
{
  struct tcp_socket *s = state;

  if(s != NULL && s->c != NULL && s->c != uip_conn) {
    /* Safe-guard: this should not happen, as the incoming event relates to
     * a previous connection */
    return;
  }
  if(uip_connected()) {
    /* Check if this connection originated in a local listen
       socket. We do this by checking the state pointer - if NULL,
       this is an incoming listen connection. If so, we need to
       connect the socket to the uip_conn and call the event
       function. */
    if(s == NULL) {
      for(s = list_head(socketlist);
	  s != NULL;
	  s = list_item_next(s)) {
	if((s->flags & TCP_SOCKET_FLAGS_LISTENING) != 0 &&
	   s->listen_port != 0 &&
	   s->listen_port == uip_htons(uip_conn->lport)) {
	  s->flags &= ~TCP_SOCKET_FLAGS_LISTENING;
          s->output_data_max_seg = uip_mss();
	  tcp_markconn(uip_conn, s);
	  call_event(s, TCP_SOCKET_CONNECTED);
	  break;
	}
      }
    } else {
      s->output_data_max_seg = uip_mss();
      call_event(s, TCP_SOCKET_CONNECTED);
    }

    if(s == NULL) {
      uip_abort();
    } else {
      if(uip_newdata()) {
        newdata(s);
      }
      senddata(s);
    }
    return;
  }

  if(uip_timedout()) {
    call_event(s, TCP_SOCKET_TIMEDOUT);
    relisten(s);
  }

  if(uip_aborted()) {
    tcp_markconn(uip_conn, NULL);
    call_event(s, TCP_SOCKET_ABORTED);
    relisten(s);

  }

  if(s == NULL) {
    uip_abort();
    return;
  }

  if(uip_acked()) {
    acked(s);
  }
  if(uip_newdata()) {
    newdata(s);
  }

  if(uip_rexmit() ||
     uip_newdata() ||
     uip_acked()) {
    senddata(s);
  } else if(uip_poll()) {
    senddata(s);
  }

  if(s->output_data_len == 0 && s->flags & TCP_SOCKET_FLAGS_CLOSING) {
    s->flags &= ~TCP_SOCKET_FLAGS_CLOSING;
    uip_close();
    s->c = NULL;
    tcp_markconn(uip_conn, NULL);
    s->c = NULL;
    /*call_event(s, TCP_SOCKET_CLOSED);*/
    relisten(s);
  }

  if(uip_closed()) {
    tcp_markconn(uip_conn, NULL);
    s->c = NULL;
    call_event(s, TCP_SOCKET_CLOSED);
    relisten(s);
  }
}
示例#8
0
文件: uip_xtcp.c 项目: aritec/sc_xtcp
void
xtcpd_appcall(void)
{
    xtcpd_state_t *s;

    if (uip_udpconnection() &&
            (uip_udp_conn->lport == HTONS(DHCPC_CLIENT_PORT) ||
             uip_udp_conn->lport == HTONS(DHCPC_SERVER_PORT))) {
#if UIP_USE_DHCP
        dhcpc_appcall();
#endif
        return;
    }

    if (uip_udpconnection()) {
        s = (xtcpd_state_t *) &(uip_udp_conn->appstate);
        if (uip_newdata()) {
            s->conn.remote_port = HTONS(UDPBUF->srcport);
            uip_ipaddr_copy(s->conn.remote_addr, BUF->srcipaddr);
        }
    }
    else if (uip_conn == NULL) {
        // dodgy uip_conn
        return;
    }
    else
        s = (xtcpd_state_t *) &(uip_conn->appstate);




    //  if (!uip_udpconnection() && uip_connected()) {
    if (uip_connected()) {
        if (!uip_udpconnection()) {
            xtcpd_init_state(s,
                             XTCP_PROTOCOL_TCP,
                             (unsigned char *) uip_conn->ripaddr,
                             uip_conn->lport,
                             uip_conn->rport,
                             uip_conn);
            xtcpd_event(XTCP_NEW_CONNECTION, s);
        }
        else {
            xtcpd_init_state(s,
                             XTCP_PROTOCOL_UDP,
                             (unsigned char *) uip_udp_conn->ripaddr,
                             uip_udp_conn->lport,
                             uip_udp_conn->rport,
                             uip_udp_conn);
            xtcpd_event(XTCP_NEW_CONNECTION, s);

        }
    }

    if (uip_acked()) {
        int len;
        if (s->linknum != -1) {
            xtcpd_service_clients_until_ready(s->linknum, xtcp_links, xtcp_num);
            len = xtcpd_send(xtcp_links[s->linknum],
                             XTCP_SENT_DATA,
                             s,
                             uip_appdata,
                             uip_udpconnection() ? XTCP_CLIENT_BUF_SIZE : uip_mss());
            if (len != 0)
                uip_send(uip_appdata, len);
        }
    }


    if (uip_newdata() && uip_len > 0) {
        if (s->linknum != -1) {
            if (!uip_udpconnection() && s->s.ack_recv_mode) {
                uip_stop();
            }
            xtcpd_service_clients_until_ready(s->linknum, xtcp_links, xtcp_num);

            xtcpd_recv(xtcp_links, s->linknum, xtcp_num,
                       s,
                       uip_appdata,
                       uip_datalen());
        }

    }

    else if (uip_aborted()) {
        xtcpd_event(XTCP_ABORTED, s);
        return;
    }
    else if (uip_timedout()) {
        xtcpd_event(XTCP_TIMED_OUT, s);
        return;
    }

    if (uip_rexmit()) {
        int len;
        if (s->linknum != -1) {
            xtcpd_service_clients_until_ready(s->linknum, xtcp_links, xtcp_num);
            len = xtcpd_send(xtcp_links[s->linknum],
                             XTCP_RESEND_DATA,
                             s,
                             uip_appdata,
                             uip_udpconnection() ? XTCP_CLIENT_BUF_SIZE : uip_mss());
            if (len != 0)
                uip_send(uip_appdata, len);
        }
    }

    if (uip_poll()) {
        uip_xtcpd_handle_poll(s);
    }

    if (uip_closed()) {
        if (!s->s.closed) {
            s->s.closed = 1;

            xtcpd_event(XTCP_CLOSED, s);
        }
        return;
    }

}
示例#9
0
void HttpDCall(	uint8_t* pBuffer,
				uint16_t nBytes,
				struct tHttpD* pSocket)
{
	uint16_t nBufSize;

	if (uip_connected())
	{
		//Initialize this connection
		pSocket->pData = g_HtmlPageDefault;
		pSocket->nDataLeft = sizeof(g_HtmlPageDefault)-1;
		pSocket->nNewlines = 0;
		pSocket->nState = STATE_CONNECTED;
		pSocket->nPrevBytes = 0xFFFF;
	}
	else if (uip_newdata() || uip_acked())
	{
		if (pSocket->nState == STATE_CONNECTED)
		{
			if (nBytes == 0)
				return;
			if (*pBuffer == 'G')
				pSocket->nState = STATE_GET_G;
			else if (*pBuffer == 'P')
				pSocket->nState = STATE_POST_P;
			nBytes--;
			pBuffer++;
		}

		if (pSocket->nState == STATE_GET_G)
		{
			if (nBytes == 0)
				return;
			if (*pBuffer == 'E')
				pSocket->nState = STATE_GET_GE;
			nBytes--;
			pBuffer++;
		}

		if (pSocket->nState == STATE_GET_GE)
		{
			if (nBytes == 0)
				return;
			if (*pBuffer == 'T')
				pSocket->nState = STATE_GET_GET;
			nBytes--;
			pBuffer++;
		}

		if (pSocket->nState == STATE_GET_GET)
		{
			if (nBytes == 0)
				return;
			if (*pBuffer == ' ')
				pSocket->nState = STATE_GOTGET;
			nBytes--;
			pBuffer++;
		}

		if (pSocket->nState == STATE_POST_P)
		{
			if (nBytes == 0)
				return;
			if (*pBuffer == 'O')
				pSocket->nState = STATE_POST_PO;
			nBytes--;
			pBuffer++;
		}

		if (pSocket->nState == STATE_POST_PO)
		{
			if (nBytes == 0)
				return;
			if (*pBuffer == 'S')
				pSocket->nState = STATE_POST_POS;
			nBytes--;
			pBuffer++;
		}

		if (pSocket->nState == STATE_POST_POS)
		{
			if (nBytes == 0)
				return;
			if (*pBuffer == 'T')
				pSocket->nState = STATE_POST_POST;
			nBytes--;
			pBuffer++;
		}

		if (pSocket->nState == STATE_POST_POST)
		{
			if (nBytes == 0)
				return;
			if (*pBuffer == ' ')
				pSocket->nState = STATE_GOTPOST;
			nBytes--;
			pBuffer++;
		}

		if (pSocket->nState == STATE_GOTPOST || pSocket->nState == STATE_GOTGET)
		{
			//Search for \r\n\r\n
			while (nBytes != 0)
			{
				if (*pBuffer == '\n')
				{
					pSocket->nNewlines++;
				}
				else if (*pBuffer == '\r')
				{
				}
				else
				{
					pSocket->nNewlines = 0;
				}

				pBuffer++;
				nBytes--;

				if (pSocket->nNewlines == 2)
				{
					//beginning found.
					if (pSocket->nState == STATE_GOTPOST)
					{
						//Initialize Parsing variables
						pSocket->nParseLeft = PARSEBYTES;
						pSocket->ParseState = PARSE_CMD;
						//start parsing
						pSocket->nState = STATE_PARSEPOST;
					}
					else if (pSocket->nState == STATE_GOTGET)
					{
						pSocket->nState = STATE_SENDHEADER;
					}
					break;
				}
			}
		}

		if (pSocket->nState == STATE_PARSEPOST)
		{
			while (nBytes--)
			{
				if (pSocket->ParseState == PARSE_CMD)
				{
					pSocket->ParseCmd = *pBuffer;
					pSocket->ParseState = PARSE_NUM10;
				}
				else if (pSocket->ParseState == PARSE_NUM10)
				{
					pSocket->ParseNum = (*pBuffer - '0') * 10;
					pSocket->ParseState = PARSE_NUM1;
				}
				else if (pSocket->ParseState == PARSE_NUM1)
				{
					pSocket->ParseNum += (*pBuffer - '0');
					pSocket->ParseState = PARSE_EQUAL;
				}
				else if (pSocket->ParseState == PARSE_EQUAL)
				{
					pSocket->ParseState = PARSE_VAL;
				}
				else if (pSocket->ParseState == PARSE_VAL)
				{
					if (pSocket->ParseCmd == 'd')
						GpioSetDdr(pSocket->ParseNum, *pBuffer - '0');
					else
						GpioSetPort(pSocket->ParseNum, *pBuffer - '0');

					pSocket->ParseState = PARSE_DELIM;
				}
				else if (pSocket->ParseState == PARSE_DELIM)
				{
					pSocket->ParseState = PARSE_CMD;
				}

				pSocket->nParseLeft--;
				pBuffer++;

				if (pSocket->nParseLeft == 0)
				{
					//finished parsing
					pSocket->nState = STATE_SENDHEADER;
					break;
				}
			}
		}

		if (pSocket->nState == STATE_SENDHEADER)
		{
			uip_send(uip_appdata, CopyHttpHeader(uip_appdata, pSocket->nDataLeft));
			pSocket->nState = STATE_SENDDATA;
			return;
		}

		if (pSocket->nState == STATE_SENDDATA)
		{
			//We have sent the HTML Header or HTML Data previously.
			//Now we send (further) Data depending on the Socket's pData pointer
			//If all data has been sent, we close the connection
			pSocket->nPrevBytes = pSocket->nDataLeft;
			nBufSize
					= CopyHttpData(uip_appdata, &pSocket->pData, &pSocket->nDataLeft, uip_mss());
			pSocket->nPrevBytes -= pSocket->nDataLeft;
			
			
			if (nBufSize == 0)
			{
				//No Data has been copied. Close connection
				uip_close();
			}
			else
			{
				//Else send copied data
				uip_send(uip_appdata, nBufSize);
			}
			return;
		}
	}
	else if (uip_rexmit())
	{
		if (pSocket->nPrevBytes == 0xFFFF)
		{
			/* Send header again */
			uip_send(uip_appdata, CopyHttpHeader(uip_appdata, pSocket->nDataLeft));
		}else
		{
			pSocket->pData -= pSocket->nPrevBytes;
			pSocket->nDataLeft += pSocket->nPrevBytes;
			pSocket->nPrevBytes = pSocket->nDataLeft;
			nBufSize
					= CopyHttpData(uip_appdata, &pSocket->pData, &pSocket->nDataLeft, uip_mss());
			pSocket->nPrevBytes -= pSocket->nDataLeft;
			
			if (nBufSize == 0)
			{
				//No Data has been copied. Close connection
				uip_close();
			}
			else
			{
				//Else send copied data
				uip_send(uip_appdata, nBufSize);
			}
		}
		return;
	}

}
示例#10
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... */
}
示例#11
0
void
httpd_handle_solometer (void)
{
  static int8_t i = 0;
  static uint8_t cont_send = 0, parsing = 0;
  uint16_t mss,page_size;
  static uip_ipaddr_t hostaddr, dnsserver;
  //char *buf;
  static uint16_t ppos;
  uint16_t lpos,wslen;
  uint8_t p_par,pct,send_packet,buf[64];

  uip_gethostaddr(&hostaddr);
#ifdef DNS_SUPPORT
  eeprom_restore(dns_server, &dnsserver, IPADDR_LEN);
#endif

  #define NUM_PAR 16
  PARAM p[NUM_PAR] = {
	      {PR_U8,"%u",(uint8_t *)&hostaddr},
	      {PR_U8,"%u",((uint8_t *)&hostaddr)+1},
	      {PR_U8,"%u",((uint8_t *)&hostaddr)+2},
	      {PR_U8,"%u",((uint8_t *)&hostaddr)+3},
	      {PR_U8,"%u",&WRID[0]},
	      {PR_STRING,"%s",post_cookie},
	      {PR_STRING,"%s",post_hostname},
	      {PR_U8,"%u",(uint8_t *)&post_hostip},
	      {PR_U8,"%u",((uint8_t *)&post_hostip)+1},
	      {PR_U8,"%u",((uint8_t *)&post_hostip)+2},
	      {PR_U8,"%u",((uint8_t *)&post_hostip)+3},
	      {PR_STRING,"%s",post_scriptname},
	      {PR_U8,"%u",(uint8_t *)&dnsserver},
	      {PR_U8,"%u",((uint8_t *)&dnsserver)+1},
	      {PR_U8,"%u",((uint8_t *)&dnsserver)+2},
	      {PR_U8,"%u",((uint8_t *)&dnsserver)+3}
  };

  //debug_printf("Handle_solometer called.\n");
  mss = uip_mss();
  if(mss > 400)
    mss = 400;
  wslen = strlen_P(website);
  
  if (uip_newdata()) {
    /* We've received new data (maybe even the first time).  We'll
      receive something like this:
      GET /solometer[?...]
    */
    /* Make sure it's zero-terminated, so we can safely use strstr */
    char *ptr = (char *)uip_appdata;
    ptr[uip_len] = 0;

    //debug_printf("Newdata: ---------\n%s\n-----------\n",ptr);

    if(strncasecmp_P (uip_appdata, PSTR ("GET /solometer"),14) == 0) {
      //debug_printf("This is the GET request header...\n");
      ptr = strstr_P (uip_appdata, PSTR("?")) + 1;
      if(!ptr || *ptr == 0) {
	//debug_printf("This is a request only. Send page.\n");
	i = 0;
      } else {
	//debug_printf("This is a set operation. Parsing...\n");
	i = solometer_parse(ptr);
      }
      //debug_printf("Setze Parsing auf 1.\n");
      parsing = 1;
    }
    
    if (parsing == 1) {
      // Do not start answering until all packets have arrived
      //debug_printf("Parsing = 1\n");
      ptr = strstr_P (uip_appdata, PSTR("\r\n\r\n"));
      if (ptr) {
	//debug_printf("Setze Parsing auf 2.\n");
	parsing = 2;
      } else {
	//debug_printf("Double NL not found. Waiting...\n");
	return;
      }
    }
    
    if (parsing == 2) {
      //debug_printf("Parsing = 2. Sende Antwort.\n");
      PASTE_RESET ();
      if(i || mss < 200) {
	PASTE_P (httpd_header_500_smt);
	cont_send = 0;
      } else {
	page_size = wslen);
	for(i=0;i<NUM_PAR;i++)
	  if(p[i].typ == PR_STRING)
	    page_size += sprintf(buf,p[i].s2,p[i].s3);
	  else
	    page_size += sprintf(buf,p[i].s2,*(uint8_t *)p[i].s3);
	PASTE_P (p1);
	sprintf(uip_appdata+uip_len,"%u\n",page_size);
	PASTE_P (p2);
	cont_send = 1;
	ppos = 0;
      }
      //debug_printf("%d: %s\n",cont_send,uip_appdata);
      PASTE_SEND ();
      parsing = 0;
      return;
    }
  }
示例#12
0
/*-----------------------------------------------------------------------------------*/
void
httpd(void)
{
  struct fs_file fsfile;  
  u8_t i;
  
  switch(uip_conn->lport) {
    /* This is the web server: */
  case htons(80):
    /* 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;
      /* Don't send any data in return; we wait for the HTTP request
	 instead. */
      uip_send(uip_appdata, 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]);
      
      if(!fs_open((const char *)&uip_appdata[4], &fsfile)) {
	PRINTLN("couldn't open file");
	fs_open(file_index_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_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();
	  }
	}
      }         
    }
    
    if(hs->state == HTTP_FUNC) {
      /* Call the CGI function. */
      if(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();
      }
    }

    if(hs->state != HTTP_FUNC && !uip_poll()) {
      /* 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... */
    return;

  default:
    /* Should never happen. */
    uip_abort();
    break;
  }  
}
示例#13
0
static uint16_t send_interrupt(struct uip_driver_s *dev, void *pvconn,
                               void *pvpriv, uint16_t flags)
{
  struct uip_conn *conn = (struct uip_conn*)pvconn;
  struct send_s *pstate = (struct send_s *)pvpriv;

  nllvdbg("flags: %04x acked: %d sent: %d\n",
          flags, pstate->snd_acked, pstate->snd_sent);

  /* If this packet contains an acknowledgement, then update the count of
   * acknowldged bytes.
   */

  if ((flags & UIP_ACKDATA) != 0)
    {
      /* The current acknowledgement number number is the (relative) offset
       * of the of the next byte needed by the receiver.  The snd_isn is the
       * offset of the first byte to send to the receiver.  The difference
       * is the number of bytes to be acknowledged.
       */

      pstate->snd_acked = uip_tcpgetsequence(TCPBUF->ackno) - pstate->snd_isn;
      nllvdbg("ACK: acked=%d sent=%d buflen=%d\n",
              pstate->snd_acked, pstate->snd_sent, pstate->snd_buflen);

      /* Have all of the bytes in the buffer been sent and acknowledged? */

      if (pstate->snd_acked >= pstate->snd_buflen)
        {
          /* Yes.  Then pstate->snd_buflen should hold the number of bytes
           * actually sent.
           */

          goto end_wait;
        }

      /* No.. fall through to send more data if necessary */
    }

  /* Check if we are being asked to retransmit data */

  else if ((flags & UIP_REXMIT) != 0)
    {
      /* Yes.. in this case, reset the number of bytes that have been sent
       * to the number of bytes that have been ACKed.
       */

      pstate->snd_sent = pstate->snd_acked;

      /* Fall through to re-send data from the last that was ACKed */
    }

 /* Check for a loss of connection */

  else if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0)
    {
      /* Report not connected */

      nllvdbg("Lost connection\n");
      pstate->snd_sent = -ENOTCONN;
      goto end_wait;
    }

   /* Check if the outgoing packet is available (it may have been claimed
    * by a sendto interrupt serving a different thread).
    */

#if 0 /* We can't really support multiple senders on the same TCP socket */
   else if (dev->d_sndlen > 0)
     {
       /* Another thread has beat us sending data, wait for the next poll */

         return flags;
      }
#endif

  /* We get here if (1) not all of the data has been ACKed, (2) we have been
   * asked to retransmit data, (3) the connection is still healthy, and (4)
   * the outgoing packet is available for our use.  In this case, we are
   * now free to send more data to receiver -- UNLESS the buffer contains
   * unprocessing incoming data.  In that event, we will have to wait for the
   * next polling cycle.
   */

  if ((flags & UIP_NEWDATA) == 0 && pstate->snd_sent < pstate->snd_buflen)
    {
      uint32_t seqno;

      /* Get the amount of data that we can send in the next packet */

      uint32_t sndlen = pstate->snd_buflen - pstate->snd_sent;
      if (sndlen > uip_mss(conn))
        {
          sndlen = uip_mss(conn);
        }

      /* Set the sequence number for this packet.  NOTE:  uIP updates
       * sndseq on recept of ACK *before* this function is called.  In that
       * case sndseq will point to the next unacknowledge byte (which might
       * have already been sent).  We will overwrite the value of sndseq
       * here before the packet is sent.
       */

      seqno = pstate->snd_sent + pstate->snd_isn;
      nllvdbg("SEND: sndseq %08x->%08x\n", conn->sndseq, seqno);
      uip_tcpsetsequence(conn->sndseq, seqno);

      /* Then set-up to send that amount of data. (this won't actually
       * happen until the polling cycle completes).
       */

      uip_send(dev, &pstate->snd_buffer[pstate->snd_sent], sndlen);

      /* Check if the destination IP address is in the ARP table.  If not,
       * then the send won't actually make it out... it will be replaced with
       * an ARP request.
       *
       * NOTE 1: This could an expensive check if there are a lot of entries
       * in the ARP table.  Hence, we only check on the first packet -- when
       * snd_sent is zero.
       *
       * NOTE 2: If we are actually harvesting IP addresses on incomming IP
       * packets, then this check should not be necessary; the MAC mapping
       * should already be in the ARP table.
       */

#if defined(CONFIG_NET_ETHERNET) && defined (CONFIG_NET_ARP_IPIN)
      if (pstate->snd_sent != 0 || uip_arp_find(conn->ripaddr) != NULL)
#endif
        {
          /* Update the amount of data sent (but not necessarily ACKed) */

          pstate->snd_sent += sndlen;
          nllvdbg("SEND: acked=%d sent=%d buflen=%d\n",
                  pstate->snd_acked, pstate->snd_sent, pstate->snd_buflen);

          /* Update the send time */

#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
          pstate->snd_time = clock_systimer();
#endif
        }
    }

  /* All data has been send and we are just waiting for ACK or re-transmit
   * indications to complete the send.  Check for a timeout.
   */

#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
  else if (send_timeout(pstate))
    {
      /* Yes.. report the timeout */

      nlldbg("SEND timeout\n");
      pstate->snd_sent = -ETIMEDOUT;
      goto end_wait;
    }
#endif /* CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */

  /* Continue waiting */

  return flags;

end_wait:
  /* Do not allow any further callbacks */

  pstate->snd_cb->flags   = 0;
  pstate->snd_cb->priv    = NULL;
  pstate->snd_cb->event   = NULL;

  /* There are no outstanding, unacknowledged bytes */

  conn->unacked           = 0;

  /* Wake up the waiting thread */

  sem_post(&pstate->snd_sem);
  return flags;
}
示例#14
0
文件: httpd-cgi.c 项目: ADVANSEE/mist
/*---------------------------------------------------------------------------*/
static unsigned short
make_addrmap(void *p)
{
  uint16_t numprinted;
  struct ip64_addrmap_entry *m;
  struct httpd_state *s = (struct httpd_state *)p;

  numprinted = 0;
  m = s->u.ptr;

  if(m != NULL && !timer_expired(&m->timer)) {
    numprinted +=
      httpd_snprintf((char *)uip_appdata, uip_mss(), "<tr><td>");
    if(numprinted >= uip_mss()) {
      return write_mss_error(20);
    }
    numprinted +=
      httpd_cgi_sprint_ip6((uip_ipaddr_t *)&m->ip6addr,
			   (char *)uip_appdata + numprinted);
    if(numprinted >= uip_mss()) {
      return write_mss_error(21);
    }
    numprinted +=
      httpd_snprintf((char *)uip_appdata + numprinted,
		     uip_mss() - numprinted, "</td><td>%d</td><td>",
		     m->ip6port);
    if(numprinted >= uip_mss()) {
      return write_mss_error(22);
    }
    numprinted +=
      httpd_sprint_ip4(&m->ip4addr,
		       (char *)uip_appdata + numprinted);
    if(numprinted >= uip_mss()) {
      return write_mss_error(23);
    }
    numprinted +=
      httpd_snprintf((char *)uip_appdata + numprinted,
		     uip_mss() - numprinted, "</td><td>%d</td><td>%d</td>",
		     m->ip4port,
		     m->mapped_port);
    if(numprinted >= uip_mss()) {
      return write_mss_error(24);
    }
    numprinted +=
      httpd_snprintf((char *)uip_appdata + numprinted,
		     uip_mss() - numprinted, "<td>%d</td>",
		     m->protocol);
    if(numprinted >= uip_mss()) {
      return write_mss_error(25);
    }

    numprinted +=
      httpd_snprintf((char *)uip_appdata + numprinted,
		     uip_mss() - numprinted, "<td>%lu</td>",
		     m->timer.interval - (clock_time() - m->timer.start));
    if(numprinted >= uip_mss()) {
      return write_mss_error(26);
    }

    numprinted +=
      httpd_snprintf((char *)uip_appdata + numprinted,
		     uip_mss() - numprinted, "<td>0x%02x</td>",
		     m->flags);
    if(numprinted >= uip_mss()) {
      return write_mss_error(27);
    }
}
  return numprinted;
}
示例#15
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);
}
示例#16
0
void TCPIP_TCPCallback(void)
{
	if (uip_acked())
		Debug_Print("[ACK] ");

	if (uip_newdata())
	{
		Debug_Print("New Data:\r\n");
		TCPIP_QueueData(uip_appdata, uip_datalen());
		
		if (TCPIP_IsDataQueueFull())
		  uip_stop();
	}

	if (uip_connected())
	{
		Debug_Print("Connected - Maximum Segment Size: 0x"); Debug_PrintHex(uip_mss() / 256); Debug_PrintHex(uip_mss() & 255); 
		Debug_Print("\r\n");
	}

	if (uip_closed())
	{
		Debug_Print("Closed - Reconnecting...");
		_delay_ms(1000);
		ConnectedState = LINKMANAGEMENT_STATE_ConnectToRemoteHost;
	}

	if (uip_aborted())
	{
		Debug_Print("Aborted - Reconnecting... ");
		_delay_ms(1000);
		ConnectedState = LINKMANAGEMENT_STATE_ConnectToRemoteHost;
	}

	if (uip_timedout())
	{
		Debug_Print("Timeout - Reconnecting...");
		uip_abort();
		_delay_ms(1000);
		ConnectedState = LINKMANAGEMENT_STATE_ConnectToRemoteHost;
	}

	if (uip_poll() && (SystemTicks > 3000))
	{
		SystemTicks = 0;
		
		Debug_Print("\r\nSending GET\r\n");
		TCPIP_SendGET();
	}
	
	if (uip_rexmit())
	{
		Debug_Print("\r\nRetransmit GET\r\n");
		TCPIP_SendGET();
	}

	if (uip_poll() && uip_stopped(TCPConnection))
	{
		if (!(TCPIP_IsDataQueueFull()))
		  uip_restart();
	}
}
示例#17
0
文件: sock.c 项目: AriZuu/picoos-net
static void netTcpAppcallMutex(NetSock* sock)
{
  if (uip_aborted()) {

    netAppcallClose(sock, NET_SOCK_PEER_ABORTED);
  }

  if (uip_timedout()) {

    netAppcallClose(sock, NET_SOCK_PEER_ABORTED);
  }

  if(uip_acked()) {

    if (sock->state == NET_SOCK_WRITING) {

      if (sock->len <= uip_mss()) {

        sock->len = 0;
        sock->state = NET_SOCK_WRITE_OK;
        posFlagSet(sock->uipChange, 0);
      }
      else {

        sock->buf = sock->buf + uip_mss();
        sock->len -= uip_mss();
        uip_send(sock->buf, sock->len);
      }
    }
  }

  if (uip_newdata()) {

    bool timeout = false;
    uint16_t dataLeft = uip_datalen();
    char* dataPtr = uip_appdata;

    while (dataLeft > 0 && !timeout) {

      while (sock->state != NET_SOCK_READING &&
             sock->state != NET_SOCK_READING_LINE && 
             !timeout) {

        posMutexUnlock(sock->mutex);
        timeout = posFlagWait(sock->sockChange, MS(500)) == 0;
        posMutexLock(sock->mutex);
      }

      if (timeout) {

        // Timeout or bad state
        uip_abort();
        netAppcallClose(sock, NET_SOCK_PEER_ABORTED);
      }
      else if (sock->state == NET_SOCK_READING_LINE) {

        char ch;

        while (dataLeft && sock->len < sock->max) {
          
          ch = *dataPtr;

          if (ch == '\r') {
       
            ++dataPtr;
            --dataLeft;
            continue;
          }

          sock->buf[sock->len] = ch;
          ++dataPtr;
          --dataLeft;
          ++sock->len;
          if (ch == '\n')
            break;
        }

        if (sock->len && (sock->len == sock->max || sock->buf[sock->len - 1] == '\n')) {

          sock->state = NET_SOCK_READ_OK;
          posFlagSet(sock->uipChange, 0);
        }
      }
      else if (sock->state == NET_SOCK_READING) {

        if (dataLeft > sock->max)
          sock->len = sock->max;
        else
          sock->len = dataLeft;

        memcpy(sock->buf, dataPtr, sock->len);
        dataLeft -= sock->len;
        dataPtr += sock->len;

        sock->state = NET_SOCK_READ_OK;
        posFlagSet(sock->uipChange, 0);
      }
    }
  }

  if (uip_rexmit()) {

    uip_send(sock->buf, sock->len);
  }

  if (uip_closed()) {

    netAppcallClose(sock, NET_SOCK_PEER_CLOSED);
  }

  if (uip_poll()) {

    if (sock->state == NET_SOCK_CLOSE) {

      uip_close();
      netAppcallClose(sock, NET_SOCK_CLOSE_OK);
    }
    else if (sock->state == NET_SOCK_WRITING) {

      uip_send(sock->buf, sock->len);
    }
  }
}
示例#18
0
/* -----------------------------------------------------------------------------
 * xtcpd_appcall
 *
 * this function is called, when a package comes in for an upper layer
 * application.
 * -------------------------------------------------------------------------- */
void
xtcpd_appcall(void)
{
  xtcpd_state_t *s;

  /* --------------- DHCP (v4)  --------------- */
  if (uip_udpconnection() &&
      (uip_udp_conn->lport == HTONS(DHCPC_CLIENT_PORT) ||
       uip_udp_conn->lport == HTONS(DHCPC_SERVER_PORT))) {
#if UIP_USE_DHCP
    dhcpc_appcall();
#endif
    return;
  }

  /* --------- set up a new connection  ---------- */
  if (uip_udpconnection()){
    s = (xtcpd_state_t *) &(uip_udp_conn->appstate);
    if (uip_newdata()) {
    	// Set remote port to upper layer state
      s->conn.remote_port = HTONS(UDPBUF->srcport);
      uip_ipaddr_copy(s->conn.remote_addr.u8, BUF->srcipaddr.u8);
    }
  } else if (uip_conn == NULL) {
      // dodgy uip_conn
      return;
  } else {
    s = (xtcpd_state_t *) &(uip_conn->appstate);
  }

  /* ------ passing new connection event up to the upper xtcp layer  ---- */
  if (uip_connected()) {
    if (!uip_udpconnection()) {
      init_xtcpd_state(s,
                       XTCP_PROTOCOL_TCP,
                       *((xtcp_ipaddr_t *) (&uip_conn->ripaddr)),
                       uip_conn->lport,
                       uip_conn->rport,
                       uip_conn);
      xtcpd_event(XTCP_NEW_CONNECTION, s);
    } else {
      init_xtcpd_state(s,
                       XTCP_PROTOCOL_UDP,
                       *((xtcp_ipaddr_t *) (&uip_udp_conn->ripaddr)),
                       uip_udp_conn->lport,
                       uip_udp_conn->rport,
                       uip_udp_conn);
      xtcpd_event(XTCP_NEW_CONNECTION, s);
    }
  }

  /* --------------- new data event to deliver  --------------- */
  if (uip_newdata() && uip_len > 0) {
    if (s->linknum != -1) {
      xtcpd_service_clients_until_ready(s->linknum, xtcp_cons.links, xtcp_cons.nr);
      xtcpd_recv(xtcp_cons.links, s->linknum, xtcp_cons.nr,
                 s,
                 uip_appdata,
                 uip_datalen());
      if (!uip_udpconnection() && s->s.ack_recv_mode) {
        uip_stop();
      }
    }
  } else if (uip_aborted()) {
    xtcpd_event(XTCP_ABORTED, s);
    return;
  } else if (uip_timedout()) {
    xtcpd_event(XTCP_TIMED_OUT, s);
    return;
  }

  /* ------------ passing acknowleg event to upper layer  ------------- */
  if (uip_acked()) {
    int len;
    if (s->linknum != -1) {
      len =
        do_xtcpd_send(xtcp_cons.links[s->linknum],
                      XTCP_SENT_DATA,
                      s,
                      uip_appdata,
                      uip_udpconnection() ? XTCP_CLIENT_BUF_SIZE : uip_mss());

      uip_send(uip_appdata, len);
    }
  }

  /* -------------- retransmit the last package  -------------- */
  if (uip_rexmit()) {
    int len;
    if (s->linknum != -1) {
      xtcpd_service_clients_until_ready(s->linknum, xtcp_cons.links, xtcp_cons.nr);
#ifdef XTCP_ENABLE_PARTIAL_PACKET_ACK
      s->conn.outstanding = 0;
#endif
      len = xtcpd_send(xtcp_cons.links[s->linknum],
                       XTCP_RESEND_DATA,
                       s,
                       uip_appdata,
                       uip_udpconnection() ? XTCP_CLIENT_BUF_SIZE : uip_mss());
      if (len != 0)
        uip_send(uip_appdata, len);
    }
  }

  /* --------------- poll a connection --------------- */
  if (uip_poll()) {
    uip_xtcpd_handle_poll(s);
  }

#if XTCP_ENABLE_PUSH_FLAG_NOTIFICATION
  if (uip_tcp_push()) {
    xtcpd_event(XTCP_PUSH_DATA, s);
  }
#endif

  /* ------------- connection close event  ------------ */
  if (uip_closed()) {
    if (!s->s.closed){
      s->s.closed = 1;

      xtcpd_event(XTCP_CLOSED, s);
    }
    return;
  }

}
示例#19
0
/*-----------------------------------------------------------------------------------*/
static void
senddata(void)
{
  register uint8_t *dataptr;
  uint16_t dataleft;

  dataptr = (uint8_t *)uip_appdata;
    
  switch(vs->sendmsg) {
  case VNC_SEND_VERSION:
    PRINTF(("Sending VERSION_STRING\n"));
    uip_send(RFB_SERVER_VERSION_STRING, sizeof(RFB_SERVER_VERSION_STRING));
    break;
  case VNC_SEND_AUTH:
    /* Send 16 bytes of encrypted challange response. */
    /* XXX: not implemented. */
    PRINTF(("Sending AUTH\n"));
    uip_send(uip_appdata, 16);
    break;
  case VNC_SEND_CINIT:
    PRINTF(("Sending CINIT\n"));
    /* Send one byte of client init. */
    *(uint8_t *)dataptr = 1;
    uip_send(uip_appdata, 1);
    break;
  case VNC_SEND_PFMT:
    PRINTF(("Sending PFMT\n"));
    ((struct rfb_set_pixel_format *)dataptr)->type = RFB_SET_PIXEL_FORMAT;

    /* Set to BGR233 pixel format. */
    ((struct rfb_set_pixel_format *)dataptr)->format.bps = 8;
    ((struct rfb_set_pixel_format *)dataptr)->format.depth = 8;
    ((struct rfb_set_pixel_format *)dataptr)->format.endian = 1;
    ((struct rfb_set_pixel_format *)dataptr)->format.truecolor = 1;
    ((struct rfb_set_pixel_format *)dataptr)->format.red_max = uip_htons(7);
    ((struct rfb_set_pixel_format *)dataptr)->format.green_max = uip_htons(7);
    ((struct rfb_set_pixel_format *)dataptr)->format.blue_max = uip_htons(3);
    ((struct rfb_set_pixel_format *)dataptr)->format.red_shift = 0;
    ((struct rfb_set_pixel_format *)dataptr)->format.green_shift = 3;
    ((struct rfb_set_pixel_format *)dataptr)->format.blue_shift = 6;

    uip_send(uip_appdata, sizeof(struct rfb_set_pixel_format));
    
    break;
  case VNC_SEND_ENCODINGS:
    PRINTF(("Sending ENCODINGS\n"));
    ((struct rfb_set_encodings *)dataptr)->type = RFB_SET_ENCODINGS;
    ((struct rfb_set_encodings *)dataptr)->encodings = uip_htons(1);
    dataptr += sizeof(struct rfb_set_encodings);
    dataptr[0] = dataptr[1] = dataptr[2] = 0;
    dataptr[3] = RFB_ENC_RAW;
    /*    ((uint8_t *)dataptr + sizeof(struct rfb_set_encodings))[4] =
      ((uint8_t *)dataptr + sizeof(struct rfb_set_encodings))[5] =
      ((uint8_t *)dataptr + sizeof(struct rfb_set_encodings))[6] = 0;
      ((uint8_t *)dataptr + sizeof(struct rfb_set_encodings))[7] = RFB_ENC_RRE;*/
    uip_send(uip_appdata, sizeof(struct rfb_set_encodings) + 4);
    break;
  case VNC_SEND_UPDATERQ:
    ((struct rfb_fb_update_request *)dataptr)->type = RFB_FB_UPDATE_REQ;
    ((struct rfb_fb_update_request *)dataptr)->incremental = 0;
    ((struct rfb_fb_update_request *)dataptr)->x = uip_htons(vnc_draw_viewport_x());
    ((struct rfb_fb_update_request *)dataptr)->y = uip_htons(vnc_draw_viewport_y());
    ((struct rfb_fb_update_request *)dataptr)->w = uip_htons(vnc_draw_viewport_w());
    ((struct rfb_fb_update_request *)dataptr)->h = uip_htons(vnc_draw_viewport_h());
    uip_send(uip_appdata, sizeof(struct rfb_fb_update_request));
    break;
  case VNC_SEND_UPDATERQ_INC:
    ((struct rfb_fb_update_request *)dataptr)->type = RFB_FB_UPDATE_REQ;
    ((struct rfb_fb_update_request *)dataptr)->incremental = 1;
    ((struct rfb_fb_update_request *)dataptr)->x = uip_htons(vnc_draw_viewport_x());
    ((struct rfb_fb_update_request *)dataptr)->y = uip_htons(vnc_draw_viewport_y());
    ((struct rfb_fb_update_request *)dataptr)->w = uip_htons(vnc_draw_viewport_w());
    ((struct rfb_fb_update_request *)dataptr)->h = uip_htons(vnc_draw_viewport_h());
    uip_send(uip_appdata, sizeof(struct rfb_fb_update_request));
    break;

  case VNC_SEND_EVENTS:

    dataleft = uip_mss();

    vs->eventptr_unacked = vs->eventptr_acked;
    while(vs->eventptr_unacked != vs->eventptr_next &&
	  dataleft > sizeof(struct rfb_key_event)) {
      switch(vs->event_queue[vs->eventptr_unacked].type) {
      case VNC_POINTER_EVENT:
	((struct rfb_pointer_event *)dataptr)->type = RFB_POINTER_EVENT;
	((struct rfb_pointer_event *)dataptr)->buttonmask =
	  vs->event_queue[vs->eventptr_unacked].ev.ptr.buttonmask;
	((struct rfb_pointer_event *)dataptr)->x =
	  uip_htons(vs->event_queue[vs->eventptr_unacked].ev.ptr.x);
	((struct rfb_pointer_event *)dataptr)->y =
	  uip_htons(vs->event_queue[vs->eventptr_unacked].ev.ptr.y);
	/*	uip_send(uip_appdata, sizeof(struct rfb_pointer_event));*/
	dataptr += sizeof(struct rfb_pointer_event);
	dataleft -= sizeof(struct rfb_pointer_event);
      break;
      case VNC_KEY_EVENT:
	PRINTF(("Send key event.\n"));
	((struct rfb_key_event *)dataptr)->type = RFB_KEY_EVENT;
	((struct rfb_key_event *)dataptr)->down =
	  vs->event_queue[vs->eventptr_unacked].ev.key.down;
	((struct rfb_key_event *)dataptr)->key[0] =
	  ((struct rfb_key_event *)dataptr)->key[1];
	((struct rfb_key_event *)dataptr)->key[2] =
	  vs->event_queue[vs->eventptr_unacked].ev.key.key >> 8;
	
	((struct rfb_key_event *)dataptr)->key[3] =
	  vs->event_queue[vs->eventptr_unacked].ev.key.key & 0xff;
	/*	uip_send(uip_appdata, sizeof(struct rfb_key_event));*/
	dataptr += sizeof(struct rfb_key_event);
	dataleft -= sizeof(struct rfb_key_event);
	break;
      case VNC_UPDATERQ_EVENT:
	((struct rfb_fb_update_request *)dataptr)->type = RFB_FB_UPDATE_REQ;
	((struct rfb_fb_update_request *)dataptr)->incremental = 0;
	((struct rfb_fb_update_request *)dataptr)->x =
	  uip_htons(vs->event_queue[vs->eventptr_unacked].ev.urq.x);
	((struct rfb_fb_update_request *)dataptr)->y =
	  uip_htons(vs->event_queue[vs->eventptr_unacked].ev.urq.y);
	((struct rfb_fb_update_request *)dataptr)->w =
	  uip_htons(vs->event_queue[vs->eventptr_unacked].ev.urq.w);
	((struct rfb_fb_update_request *)dataptr)->h =
	  uip_htons(vs->event_queue[vs->eventptr_unacked].ev.urq.h);
	/*	uip_send(uip_appdata, sizeof(struct rfb_fb_update_request));    */
	dataptr += sizeof(struct rfb_fb_update_request);
	dataleft -= sizeof(struct rfb_fb_update_request);
	break;
      }
      vs->eventptr_unacked = (vs->eventptr_unacked + 1) % VNC_EVENTQUEUE_SIZE;
    }

    uip_send(uip_appdata, uip_mss() - dataleft);
    break;
  }
}
示例#20
0
static uint16_t send_interrupt(FAR struct uip_driver_s *dev, FAR void *pvconn,
                               FAR void *pvpriv, uint16_t flags)
{
  FAR struct uip_conn *conn = (FAR struct uip_conn*)pvconn;
  FAR struct send_s *pstate = (FAR struct send_s *)pvpriv;

  nllvdbg("flags: %04x acked: %d sent: %d\n",
          flags, pstate->snd_acked, pstate->snd_sent);

  /* If this packet contains an acknowledgement, then update the count of
   * acknowledged bytes.
   */

  if ((flags & UIP_ACKDATA) != 0)
    {
      /* Update the timeout */

#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
      pstate->snd_time = clock_systimer();
#endif

      /* The current acknowledgement number number is the (relative) offset
       * of the of the next byte needed by the receiver.  The snd_isn is the
       * offset of the first byte to send to the receiver.  The difference
       * is the number of bytes to be acknowledged.
       */

      pstate->snd_acked = uip_tcpgetsequence(TCPBUF->ackno) - pstate->snd_isn;
      nllvdbg("ACK: acked=%d sent=%d buflen=%d\n",
              pstate->snd_acked, pstate->snd_sent, pstate->snd_buflen);

      /* Have all of the bytes in the buffer been sent and acknowledged? */

      if (pstate->snd_acked >= pstate->snd_buflen)
        {
          /* Yes.  Then pstate->snd_buflen should hold the number of bytes
           * actually sent.
           */

          goto end_wait;
        }

      /* No.. fall through to send more data if necessary */
    }

  /* Check if we are being asked to retransmit data */

  else if ((flags & UIP_REXMIT) != 0)
    {
      /* Yes.. in this case, reset the number of bytes that have been sent
       * to the number of bytes that have been ACKed.
       */

      pstate->snd_sent = pstate->snd_acked;

#if defined(CONFIG_NET_TCP_SPLIT)
      /* Reset the even/odd indicator to even since we need to
       * retransmit.
       */

      pstate->snd_odd = false;
#endif

      /* Fall through to re-send data from the last that was ACKed */
    }

 /* Check for a loss of connection */

  else if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0)
    {
      /* Report not connected */

      nllvdbg("Lost connection\n");

      net_lostconnection(pstate->snd_sock, flags);
      pstate->snd_sent = -ENOTCONN;
      goto end_wait;
    }

   /* Check if the outgoing packet is available (it may have been claimed
    * by a sendto interrupt serving a different thread).
    */

#if 0 /* We can't really support multiple senders on the same TCP socket */
   else if (dev->d_sndlen > 0)
     {
       /* Another thread has beat us sending data, wait for the next poll */

         return flags;
      }
#endif

  /* We get here if (1) not all of the data has been ACKed, (2) we have been
   * asked to retransmit data, (3) the connection is still healthy, and (4)
   * the outgoing packet is available for our use.  In this case, we are
   * now free to send more data to receiver -- UNLESS the buffer contains
   * unprocessed incoming data.  In that event, we will have to wait for the
   * next polling cycle.
   */

  if ((flags & UIP_NEWDATA) == 0 && pstate->snd_sent < pstate->snd_buflen)
    {
      uint32_t seqno;

      /* Get the amount of data that we can send in the next packet */

      uint32_t sndlen = pstate->snd_buflen - pstate->snd_sent;


#if defined(CONFIG_NET_TCP_SPLIT)

      /* RFC 1122 states that a host may delay ACKing for up to 500ms but
       * must respond to every second  segment).  This logic here will trick
       * the RFC 1122 recipient into responding sooner.  This logic will be
       * activated if:
       *
       *   1. An even number of packets has been send (where zero is an even
       *      number),
       *   2. There is more data be sent (more than or equal to
       *      CONFIG_NET_TCP_SPLIT_SIZE), but
       *   3. Not enough data for two packets.
       *
       * Then we will split the remaining, single packet into two partial
       * packets.  This will stimulate the RFC 1122 peer to ACK sooner.
       *
       * Don't try to split very small packets (less than CONFIG_NET_TCP_SPLIT_SIZE).
       * Only the first even packet and the last odd packets could have
       * sndlen less than CONFIG_NET_TCP_SPLIT_SIZE.  The value of sndlen on
       * the last even packet is guaranteed to be at least MSS/2 by the
       * logic below.
       */

      if (sndlen >= CONFIG_NET_TCP_SPLIT_SIZE)
        {
          /* sndlen is the number of bytes remaining to be sent.
           * uip_mss(conn) will return the number of bytes that can sent
           * in one packet.  The difference, then, is the number of bytes
           * that would be sent in the next packet after this one.
           */

          int32_t next_sndlen = sndlen - uip_mss(conn);

          /*  Is this the even packet in the packet pair transaction? */

          if (!pstate->snd_odd)
            {
              /* next_sndlen <= 0 means that the entire remaining data
               * could fit into this single packet.  This is condition
               * in which we must do the split.
               */

              if (next_sndlen <= 0)
                {
                  /* Split so that there will be an odd packet.  Here
                   * we know that 0 < sndlen <= MSS
                   */

                  sndlen = (sndlen / 2) + 1;
                }
            }

          /* No... this is the odd packet in the packet pair transaction */

          else
            {
              /* Will there be another (even) packet afer this one?
               * (next_sndlen > 0)  Will the split condition occur on that
               * next, even packet? ((next_sndlen - uip_mss(conn)) < 0) If
               * so, then perform the split now to avoid the case where the
               * byte count is less than CONFIG_NET_TCP_SPLIT_SIZE on the
               * next pair.
               */

              if (next_sndlen > 0 && (next_sndlen - uip_mss(conn)) < 0)
                {
                  /* Here, we know that sndlen must be MSS < sndlen <= 2*MSS
                   * and so (sndlen / 2) is <= MSS.
                   */

                  sndlen /= 2;
                }
            }
        }

      /* Toggle the even/odd indicator */

      pstate->snd_odd ^= true;

#endif /* CONFIG_NET_TCP_SPLIT */

      if (sndlen > uip_mss(conn))
        {
          sndlen = uip_mss(conn);
        }

      /* Check if we have "space" in the window */

      if ((pstate->snd_sent - pstate->snd_acked + sndlen) < conn->winsize)
        {
          /* Set the sequence number for this packet.  NOTE:  uIP updates
           * sndseq on recept of ACK *before* this function is called.  In that
           * case sndseq will point to the next unacknowledged byte (which might
           * have already been sent).  We will overwrite the value of sndseq
           * here before the packet is sent.
           */

          seqno = pstate->snd_sent + pstate->snd_isn;
          nllvdbg("SEND: sndseq %08x->%08x\n", conn->sndseq, seqno);
          uip_tcpsetsequence(conn->sndseq, seqno);

          /* Then set-up to send that amount of data. (this won't actually
           * happen until the polling cycle completes).
           */

          uip_send(dev, &pstate->snd_buffer[pstate->snd_sent], sndlen);

          /* Check if the destination IP address is in the ARP table.  If not,
           * then the send won't actually make it out... it will be replaced with
           * an ARP request.
           *
           * NOTE 1: This could be an expensive check if there are a lot of entries
           * in the ARP table.  Hence, we only check on the first packet -- when
           * snd_sent is zero.
           *
           * NOTE 2: If we are actually harvesting IP addresses on incoming IP
           * packets, then this check should not be necessary; the MAC mapping
           * should already be in the ARP table.
           */

#if defined(CONFIG_NET_ETHERNET) && !defined(CONFIG_NET_ARP_IPIN)
         if (pstate->snd_sent != 0 || uip_arp_find(conn->ripaddr) != NULL)
#endif
            {
              /* Update the amount of data sent (but not necessarily ACKed) */

              pstate->snd_sent += sndlen;
              nllvdbg("SEND: acked=%d sent=%d buflen=%d\n",
                      pstate->snd_acked, pstate->snd_sent, pstate->snd_buflen);

            }
        }
    }

  /* All data has been sent and we are just waiting for ACK or re-transmit
   * indications to complete the send.  Check for a timeout.
   */

#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
  if (send_timeout(pstate))
    {
      /* Yes.. report the timeout */

      nlldbg("SEND timeout\n");
      pstate->snd_sent = -ETIMEDOUT;
      goto end_wait;
    }
#endif /* CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */

  /* Continue waiting */

  return flags;

end_wait:
  /* Do not allow any further callbacks */

  pstate->snd_cb->flags   = 0;
  pstate->snd_cb->priv    = NULL;
  pstate->snd_cb->event   = NULL;

  /* There are no outstanding, unacknowledged bytes */

  conn->unacked           = 0;

  /* Wake up the waiting thread */

  sem_post(&pstate->snd_sem);
  return flags;
}
/*---------------------------------------------------------------------------*/
static PT_THREAD( handle_script ( struct httpd_state *s ) )
{
	char	*ptr;

	PT_BEGIN( &s->scriptpt );
	( void ) PT_YIELD_FLAG;
	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
			{
				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 );
}
示例#22
0
文件: httpd-cgi.c 项目: ADVANSEE/mist
/*---------------------------------------------------------------------------*/
static unsigned short
make_neighbor(void *p)
{
  uint16_t numprinted = 0;
  uip_ds6_nbr_t *nbr;
  
  struct httpd_state *s = (struct httpd_state *)p;

  nbr = s->u.ptr;
  /*  for(i = 0; i < UIP_DS6_NBR_NB; i++)*/ {
    /*    if(uip_ds6_nbr_cache[i].isused)*/ {
    
      numprinted +=
          httpd_snprintf((char *)uip_appdata, uip_mss(), httpd_cgi_addrh);
      if(numprinted >= uip_mss()) {
        return write_mss_error(4);
      }

      numprinted +=
          httpd_cgi_sprint_ip6(&nbr->ipaddr,
                               (char *)uip_appdata + numprinted);
      if(numprinted >= uip_mss()) {
        return write_mss_error(5);
      }

      if(simple_udp_ping_has_reply(&nbr->ipaddr)) {
        int delay = simple_udp_ping_get_delay(&nbr->ipaddr);
        numprinted +=
            httpd_snprintf((char *)uip_appdata + numprinted,
                           uip_mss() - numprinted, "</td><td>%u ms", delay);
        if(numprinted >= uip_mss()) {
          return write_mss_error(6);
        }
      } else if(simple_udp_ping_has_sent(&nbr->ipaddr)) {
        numprinted +=
            httpd_snprintf((char *)uip_appdata + numprinted,
                           uip_mss() - numprinted, "</td><td>Ping scheduled...");
        if(numprinted >= uip_mss()) {
          return write_mss_error(7);
        }
      } else {
        numprinted +=
            httpd_snprintf((char *)uip_appdata + numprinted,
                           uip_mss() - numprinted, "</td><td>-");
        if(numprinted >= uip_mss()) {
          return write_mss_error(8);
        }
      }

      numprinted +=
          httpd_snprintf((char *)uip_appdata + numprinted,
                         uip_mss() - numprinted, httpd_cgi_addrb);
      if(numprinted >= uip_mss()) {
        return write_mss_error(9);
      }
    }
  }

  return numprinted;
}