Esempio n. 1
0
/**
 * Create a new netconn (of a specific type) that has a callback function.
 * The corresponding pcb is also created.
 *
 * @param t the type of 'connection' to create (@see enum netconn_type)
 * @param proto the IP protocol for RAW IP pcbs
 * @param callback a function to call on status changes (RX available, TX'ed)
 * @return a newly allocated struct netconn or
 *         NULL on memory error
 */
struct netconn*
netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback)
{
  struct netconn *conn;
  struct api_msg msg;

  conn = netconn_alloc(t, callback);
  if (conn != NULL) {
    msg.function = do_newconn;
    msg.msg.msg.n.proto = proto;
    msg.msg.conn = conn;
    if (TCPIP_APIMSG(&msg) != ERR_OK) {
      LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL);
      LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed));
      LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox));
#if LWIP_TCP
      LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox));
#endif /* LWIP_TCP */
      sys_sem_free(&conn->op_completed);
      sys_mbox_free(&conn->recvmbox);
      memp_free(MEMP_NETCONN, conn);
      return NULL;
    }
  }
  return conn;
}
Esempio n. 2
0
/** Delete a semaphore
 * @param sem semaphore to delete */
void sys_sem_free(sys_sem_t *sem)
{
	if (sys_sem_valid(sem)) {
		SYS_STATS_DEC(sem.used);
		vSemaphoreDelete(*sem);
	}
}
Esempio n. 3
0
/**
 * Create a new netconn (of a specific type) that has a callback function.
 * The corresponding pcb is also created.
 *
 * @param t the type of 'connection' to create (@see enum netconn_type)
 * @param proto the IP protocol for RAW IP pcbs
 * @param callback a function to call on status changes (RX available, TX'ed)
 * @return a newly allocated struct netconn or
 *         NULL on memory error
 */
struct netconn*
netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback)
{
  struct netconn *conn;
  API_MSG_VAR_DECLARE(msg);

  conn = netconn_alloc(t, callback);
  if (conn != NULL) {
    err_t err;
    API_MSG_VAR_ALLOC_DONTFAIL(msg);
    API_MSG_VAR_REF(msg).msg.msg.n.proto = proto;
    API_MSG_VAR_REF(msg).msg.conn = conn;
    TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_newconn, err);
    API_MSG_VAR_FREE(msg);
    if (err != ERR_OK) {
      LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL);
      LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox));
#if LWIP_TCP
      LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox));
#endif /* LWIP_TCP */
#if !LWIP_NETCONN_SEM_PER_THREAD
      LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed));
      sys_sem_free(&conn->op_completed);
#endif /* !LWIP_NETCONN_SEM_PER_THREAD */
      sys_mbox_free(&conn->recvmbox);
      memp_free(MEMP_NETCONN, conn);
      return NULL;
    }
  }
  return conn;
}
Esempio n. 4
0
/**
 * \brief CGI request search engine.
 *
 * \param name CGI request name.
 * \param table CGI handler table.
 * \return A valid function handler for the specified CGI request, NULL otherwise.
 */
http_handler_t cgi_search(const char *name, HttpCGI *table)
{
	/* Allocate the CGI semaphore. */
	/* This is necessary to avoid race conditions on tx_buf.*/
	if (!sys_sem_valid(&cgi_sem)) {
		sys_sem_new(&cgi_sem, 1);
	}

	if (!table) {
		return NULL;
	}

	int i = 0;
	const char *ext = get_ext(name);

	while (table[i].name) {
		if (ext && table[i].type == CGI_MATCH_EXT) {
			if (!strcmp(table[i].name, ext)) {
				break;
			}
		} else if (table[i].type == CGI_MATCH_NAME) {
			if (strstr(name, table[i].name) != NULL) {
				break;
			}
		} else { /* (table[i].type == CGI_MATCH_WORD) */
			if (!strcmp(table[i].name, name)) {
				break;
			}
		}

		i++;
	}

	return table[i].handler;
}
Esempio n. 5
0
/**
 * Call the lower part of a netconn_* function
 * This function is then running in the thread context
 * of tcpip_thread and has exclusive access to lwIP core code.
 *
 * @param apimsg a struct containing the function to call and its parameters
 * @return ERR_OK if the function was called, another err_t if not
 */
err_t
tcpip_apimsg(struct api_msg *apimsg)
{
  TCPIP_MSG_VAR_DECLARE(msg);
#ifdef LWIP_DEBUG
  /* catch functions that don't set err */
  apimsg->msg.err = ERR_VAL;
#endif

  if (sys_mbox_valid_val(mbox)) {
    TCPIP_MSG_VAR_ALLOC(msg);
    TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API;
    TCPIP_MSG_VAR_REF(msg).msg.apimsg = apimsg;
#if LWIP_NETCONN_SEM_PER_THREAD
    apimsg->msg.op_completed_sem = LWIP_NETCONN_THREAD_SEM_GET();
    LWIP_ASSERT("netconn semaphore not initialized",
      sys_sem_valid(apimsg->msg.op_completed_sem));
#endif
    sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg));
    sys_arch_sem_wait(LWIP_API_MSG_SEM(&apimsg->msg), 0);
    TCPIP_MSG_VAR_FREE(msg);
    return apimsg->msg.err;
  }
  return ERR_VAL;
}
Esempio n. 6
0
/** Wait for a semaphore for the specified timeout
 * @param sem the semaphore to wait for
 * @param timeout timeout in milliseconds to wait (0 = wait forever)
 * @return time (in milliseconds) waited for the semaphore
 *         or SYS_ARCH_TIMEOUT on timeout */
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
{
	TickType_t xStartTime, xEndTime, xElapsed;
	u32_t xReturn;

	if (!sys_sem_valid(sem)) { /** NON-VALID SEM */
		return SYS_ARCH_TIMEOUT;
	}

	xStartTime = xTaskGetTickCount();

	if( timeout != 0UL ) {
		if( xSemaphoreTake( *sem, timeout / portTICK_PERIOD_MS ) == pdTRUE ) {
			xEndTime = xTaskGetTickCount();
			xElapsed = (xEndTime - xStartTime) * portTICK_PERIOD_MS;
			xReturn = xElapsed;
		} else {
			xReturn = SYS_ARCH_TIMEOUT;
		}
	} else {
		while( xSemaphoreTake( *sem, portMAX_DELAY ) != pdTRUE );
		xEndTime = xTaskGetTickCount();
		xElapsed = ( xEndTime - xStartTime ) * portTICK_PERIOD_MS;

		if( xElapsed == 0UL ) {
			xElapsed = 1UL;
		}
		xReturn = xElapsed;
	}

	return xReturn;
}
Esempio n. 7
0
File: tcpip.c Progetto: wosayttn/aos
/**
 * Sends a message to TCPIP thread to call a function. Caller thread blocks on
 * on a provided semaphore, which ist NOT automatically signalled by TCPIP thread,
 * this has to be done by the user.
 * It is recommended to use LWIP_TCPIP_CORE_LOCKING since this is the way
 * with least runtime overhead.
 *
 * @param fn function to be called from TCPIP thread
 * @param apimsg argument to API function
 * @param sem semaphore to wait on
 * @return ERR_OK if the function was called, another err_t if not
 */
err_t
tcpip_send_msg_wait_sem(tcpip_callback_fn fn, void *apimsg, sys_sem_t* sem)
{
#if LWIP_TCPIP_CORE_LOCKING
  LWIP_UNUSED_ARG(sem);
  LOCK_TCPIP_CORE();
  fn(apimsg);
  UNLOCK_TCPIP_CORE();
  return ERR_OK;
#else /* LWIP_TCPIP_CORE_LOCKING */
  TCPIP_MSG_VAR_DECLARE(msg);

  LWIP_ASSERT("semaphore not initialized", sys_sem_valid(sem));
  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));

  TCPIP_MSG_VAR_ALLOC(msg);
  TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API;
  TCPIP_MSG_VAR_REF(msg).msg.api_msg.function = fn;
  TCPIP_MSG_VAR_REF(msg).msg.api_msg.msg = apimsg;
  sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg));
  sys_arch_sem_wait(sem, 0);
  TCPIP_MSG_VAR_FREE(msg);
  return ERR_OK;
#endif /* LWIP_TCPIP_CORE_LOCKING */
}
Esempio n. 8
0
/**
 * Delete the pcb inside a netconn.
 * Called from netconn_delete.
 *
 * @param msg the api_msg_msg pointing to the connection
 */
void
lwip_netconn_do_delconn(struct api_msg_msg *msg)
{
  /* @todo TCP: abort running write/connect? */
 if ((msg->conn->state != NETCONN_NONE) &&
     (msg->conn->state != NETCONN_LISTEN) &&
     (msg->conn->state != NETCONN_CONNECT)) {
    /* this only happens for TCP netconns */
    LWIP_ASSERT("NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP",
                NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP);
    msg->err = ERR_INPROGRESS;
  } else {
    LWIP_ASSERT("blocking connect in progress",
      (msg->conn->state != NETCONN_CONNECT) || IN_NONBLOCKING_CONNECT(msg->conn));
    /* Drain and delete mboxes */
    netconn_drain(msg->conn);

    if (msg->conn->pcb.tcp != NULL) {

      switch (NETCONNTYPE_GROUP(msg->conn->type)) {
#if LWIP_RAW
      case NETCONN_RAW:
        raw_remove(msg->conn->pcb.raw);
        break;
#endif /* LWIP_RAW */
#if LWIP_UDP
      case NETCONN_UDP:
        msg->conn->pcb.udp->recv_arg = NULL;
        udp_remove(msg->conn->pcb.udp);
        break;
#endif /* LWIP_UDP */
#if LWIP_TCP
      case NETCONN_TCP:
        LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL &&
          msg->conn->write_offset == 0);
        msg->conn->state = NETCONN_CLOSE;
        msg->msg.sd.shut = NETCONN_SHUT_RDWR;
        msg->conn->current_msg = msg;
        lwip_netconn_do_close_internal(msg->conn);
        /* API_EVENT is called inside lwip_netconn_do_close_internal, before releasing
           the application thread, so we can return at this point! */
        return;
#endif /* LWIP_TCP */
      default:
        break;
      }
      msg->conn->pcb.tcp = NULL;
    }
    /* tcp netconns don't come here! */

    /* @todo: this lets select make the socket readable and writable,
       which is wrong! errfd instead? */
    API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0);
    API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0);
  }
  if (sys_sem_valid(&msg->conn->op_completed)) {
    sys_sem_signal(&msg->conn->op_completed);
  }
}
Esempio n. 9
0
/** Signals a semaphore
 * @param sem the semaphore to signal */
void sys_sem_signal(sys_sem_t *sem)
{
	portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;

	if (sys_sem_valid(sem)) {
		if( exc_sense() ) { /** in interrupt */
			xSemaphoreGiveFromISR( *sem, &xHigherPriorityTaskWoken );
		} else {
			xSemaphoreGive( *sem );
		}
	}
}
Esempio n. 10
0
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t count)
{
    LWIP_ASSERT("invalid semaphor", sys_sem_valid(sem));
    if (count != 0) {
        uint64_t stop, start;
        start = xtimer_now_usec64();
        int res = sema_wait_timed((sema_t *)sem, count * US_PER_MS);
        stop = xtimer_now_usec64() - start;
        if (res == -ETIMEDOUT) {
            return SYS_ARCH_TIMEOUT;
        }
        return (u32_t)(stop / US_PER_MS);
    }
    else {
        sema_wait_timed((sema_t *)sem, 0);
        return 0;
    }
}
Esempio n. 11
0
/** Create a new semaphore
 * @param sem pointer to the semaphore to create
 * @param count initial count of the semaphore
 * @return ERR_OK if successful, another err_t otherwise */
err_t sys_sem_new(sys_sem_t *sem, u8_t count)
{
	err_t ercd = ERR_MEM;

	vSemaphoreCreateBinary((*sem));

	if (sys_sem_valid(sem)) {
		if (count == 0) {
			if (xSemaphoreTake(*sem, 1) == pdPASS) {
				ercd = ERR_OK;
				SYS_STATS_INC_USED(sem);
			}
		} else {
			ercd = ERR_OK;
			SYS_STATS_INC_USED(sem);
		}
	} else {
		SYS_STATS_INC(sem.err);
	}

	return ercd;
}
Esempio n. 12
0
void sys_sem_signal(sys_sem_t *sem)
{
    LWIP_ASSERT("invalid semaphor", sys_sem_valid(sem));
    sema_post((sema_t *)sem);
}
Esempio n. 13
0
/**
 * Call the lower part of a netconn_* function
 * This function is then running in the thread context
 * of tcpip_thread and has exclusive access to lwIP core code.
 *
 * @param apimsg a struct containing the function to call and its parameters
 * @return ERR_OK if the function was called, another err_t if not
 */
static err_t
tcpip_apimsg(struct api_msg *apimsg)
{
#ifdef LWIP_DEBUG
  /* catch functions that don't set err */
  apimsg->msg.err = ERR_VAL;
#endif
#if LWIP_NETCONN_SEM_PER_THREAD
  apimsg->msg.op_completed_sem = LWIP_NETCONN_THREAD_SEM_GET();
  LWIP_ASSERT("netconn semaphore not initialized",
  sys_sem_valid(apimsg->msg.op_completed_sem));
#endif

#ifdef LWIP_ESP8266    
//#if 0
    sys_sem_t *op_sem_tmp = NULL;
    if(apimsg->function == lwip_netconn_do_write)
        op_sem_tmp = LWIP_API_MSG_SND_SEM(&apimsg->msg);
    else
        op_sem_tmp = LWIP_API_MSG_SEM(&apimsg->msg);
    if (tcpip_send_api_msg(apimsg->function, &apimsg->msg, op_sem_tmp) == ERR_OK) {
#else
    if (tcpip_send_api_msg(apimsg->function, &apimsg->msg, LWIP_API_MSG_SEM(&apimsg->msg)) == ERR_OK) {
#endif

        return apimsg->msg.err;
    }
    
  return ERR_VAL;
}
#endif /* !LWIP_TCPIP_CORE_LOCKING */

/**
 * Create a new netconn (of a specific type) that has a callback function.
 * The corresponding pcb is also created.
 *
 * @param t the type of 'connection' to create (@see enum netconn_type)
 * @param proto the IP protocol for RAW IP pcbs
 * @param callback a function to call on status changes (RX available, TX'ed)
 * @return a newly allocated struct netconn or
 *         NULL on memory error
 */
struct netconn*
netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback)
{
  struct netconn *conn;
  API_MSG_VAR_DECLARE(msg);

  conn = netconn_alloc(t, callback);
  if (conn != NULL) {
    err_t err;
    API_MSG_VAR_ALLOC_DONTFAIL(msg);
    API_MSG_VAR_REF(msg).msg.msg.n.proto = proto;
    API_MSG_VAR_REF(msg).msg.conn = conn;
    TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_newconn, err);
    API_MSG_VAR_FREE(msg);
    if (err != ERR_OK) {
      LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL);
      LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox));
#if LWIP_TCP
      LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox));
#endif /* LWIP_TCP */
#if !LWIP_NETCONN_SEM_PER_THREAD
      LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed));
      sys_sem_free(&conn->op_completed);

#ifdef LWIP_ESP8266
        sys_sem_free(&conn->snd_op_completed);
#endif

#endif /* !LWIP_NETCONN_SEM_PER_THREAD */
      sys_mbox_free(&conn->recvmbox);
      memp_free(MEMP_NETCONN, conn);
      return NULL;
    }
  }
  return conn;
}

/**
 * Close a netconn 'connection' and free its resources.
 * UDP and RAW connection are completely closed, TCP pcbs might still be in a waitstate
 * after this returns.
 *
 * @param conn the netconn to delete
 * @return ERR_OK if the connection was deleted
 */
err_t
netconn_delete(struct netconn *conn)
{
  err_t err;
  API_MSG_VAR_DECLARE(msg);

  /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */
  if (conn == NULL) {
    return ERR_OK;
  }

  API_MSG_VAR_ALLOC(msg);
  API_MSG_VAR_REF(msg).msg.conn = conn;
#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER
  /* get the time we started, which is later compared to
     sys_now() + conn->send_timeout */
  API_MSG_VAR_REF(msg).msg.msg.sd.time_started = sys_now();
#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
#if LWIP_TCP
  API_MSG_VAR_REF(msg).msg.msg.sd.polls_left =
    ((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1;
#endif /* LWIP_TCP */
#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
  TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_delconn, err);
  API_MSG_VAR_FREE(msg);

  if (err != ERR_OK) {
    return err;
  }

  netconn_free(conn);

  return ERR_OK;
}
Esempio n. 14
0
void ethernetif_frame_ready()
{
  EMAC_IntCmd(EMAC_INT_RX_DONE, DISABLE);
	if (sys_sem_valid(&sem_recv))
		sys_sem_signal(&sem_recv);
}