Hi,

  For a better understanding I give a part of the code of my HTTP server:

  ===============================================

  void httpd_init(void)
{
  struct tcp_pcb *pcb;

  pcb = tcp_new();
  tcp_bind(pcb, IP_ADDR_ANY, 80);
  pcb = tcp_listen(pcb);
  tcp_accept(pcb, http_accept);
}

  ===============================================

  static err_t
http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
{
    struct http_connect_state* hcs;

    tcp_setprio(pcb, TCP_PRIO_MIN);

    /* Allocate memory for the structure that holds the state of the connection. */
    hcs = mem_malloc(sizeof(struct http_connect_state));

    if (hcs == NULL) {
        return ERR_MEM;
    }

    /* Initialize the structure. */
    hcs->file            = NULL;
    hcs->resource_id    = 0;
    hcs->method_id        = 0;
    hcs->retries        = 0;

    /* Tell TCP that this is the structure we wish to be passed for our callbacks. */
    tcp_arg(pcb, hcs);

    /* Tell TCP that we wish to be informed of incoming data by a call to the http_recv() function. */
    tcp_recv(pcb, http_recv);

    tcp_err(pcb, conn_err);

    tcp_poll(pcb, http_poll, 4);

    return ERR_OK;
}

  ===============================================

  static err_t
http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
    struct http_connect_state* hcs;

    hcs = arg;

    if (ERR_OK == err)
    {
          if (NULL != p)
        {
            /* Inform TCP that we have taken the data. */
            tcp_recved(pcb, p->tot_len);
   
            if (hcs->file == NULL)
            {
                ProcessHttpRequest(hcs, p, &(pcb->remote_ip));
               
                if (hcs->file != NULL)
                {
                    pbuf_free(p);
                    send_data(pcb, hcs);
       
                    /* Tell TCP that we wish be to informed of data that has been                      successfully sent by a call to the http_sent() function. */
                    tcp_sent(pcb, http_sent);
                }
                else
                {
                    pbuf_free(p);
                    p = NULL;
                }             
            }
            else
            {
                pbuf_free(p);
                p = NULL;
            }
        }
   
        if (NULL == p)
        {
            close_conn(pcb, hcs);
        }
    }

    return err;
}

  ===============================================

  static err_t
http_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
  struct http_connect_state* hcs;

  if(arg != NULL)
  {
      hcs = arg;
      hcs->retries = 0;
      send_data(pcb, hcs);
  }

  return ERR_OK;
}

  ===============================================

  static void
close_conn(struct tcp_pcb *pcb, struct http_connect_state* hcs)
{
    tcp_arg(pcb, NULL);
    tcp_sent(pcb, NULL);
    tcp_recv(pcb, NULL);

    if(hcs->file) {
        wfs_close(hcs->file);
        hcs->file = NULL;
    }

    mem_free(hcs);
    tcp_close(pcb);
}

  ===============================================

As you can see at the HTTP init, the http_accept is set as callback for ACCEPT and in http_recv, http_sent is set as callback which will be called by TCP_EVENT_SENT.

When I use a single web browser there is no problem: the arg value passed to http_sent is never NULL. But when I launch another web browser, this parameter becomes sometimes NULL. It seems to be when the stack receives the new SYN frame from the client.

  You said "That could be a hint that you are writing beyond allocated memory
somwhere and overwrite the memory where the PCB lies with zeros". But I always check the returned value when I make a memory allocation. If the functions used for memory allocation return an invalid space => there is a bug in the stack!

  Baptiste

  Quoting "goldsi...@gmx.de" <goldsi...@gmx.de>:
Baptiste Chaboud-crousaz wrote:

Sometimes, the face trouble with my callback http_connect - called  by the macro TCP_EVENT_SENT - because "arg" is null.


I don't understand that one:
a) there is no function 'http_connect' in the code you posted
b) TCP_EVENT_SENT calls the function set by calling tcp_sent(pcb, fn) -
the code you posted doesn't call tcp_sent().
c) I would have thought a connect function would be used with a client,
not a server - whereas an accept function (as you posted) is used with
a server, not a client)

My understanding is that the http_accept function binds a pcb to an  argument by a call to tcp_arg(...). I don't undersatnd why  sometimes my callback is called with a NULL arg!!!

This issue seems to be avoided/limited by increasing the size of  MEM_SIZE and PBUF_POOL_SIZE.


That could be a hint that you are writing beyond allocated memory
somwhere and overwrite the memory where the PCB lies with zeros...

If anybody has an idea, let me knwo about it...


Except for the above, I'm afraid I don't have an idea. Unless you call
*tcp_arg(pcb, NULL) somewhere else, of course...*

Does the argument get NULL during the connection or right at the start?


Simon


_______________________________________________
lwip-users mailing list
lwip-users@nongnu.org
http://lists.nongnu.org/mailman/listinfo/lwip-users


_______________________________________________
lwip-users mailing list
lwip-users@nongnu.org
http://lists.nongnu.org/mailman/listinfo/lwip-users

Reply via email to