⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 api_msg.c

📁 lwip-1.4.0
💻 C
📖 第 1 页 / 共 3 页
字号:
    udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);    break;#endif /* LWIP_UDP */#if LWIP_TCP  case NETCONN_TCP:    msg->conn->pcb.tcp = tcp_new();    if(msg->conn->pcb.tcp == NULL) {      msg->err = ERR_MEM;      break;    }    setup_tcp(msg->conn);    break;#endif /* LWIP_TCP */  default:    /* Unsupported netconn type, e.g. protocol disabled */    msg->err = ERR_VAL;    break;  }}/** * Create a new pcb of a specific type inside a netconn. * Called from netconn_new_with_proto_and_callback. * * @param msg the api_msg_msg describing the connection type */voiddo_newconn(struct api_msg_msg *msg){  msg->err = ERR_OK;  if(msg->conn->pcb.tcp == NULL) {    pcb_new(msg);  }  /* Else? This "new" connection already has a PCB allocated. */  /* Is this an error condition? Should it be deleted? */  /* We currently just are happy and return. */  TCPIP_APIMSG_ACK(msg);}/** * Create a new netconn (of a specific type) that has a callback function. * The corresponding pcb is NOT 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_alloc(enum netconn_type t, netconn_callback callback){  struct netconn *conn;  int size;  conn = (struct netconn *)memp_malloc(MEMP_NETCONN);  if (conn == NULL) {    return NULL;  }  conn->last_err = ERR_OK;  conn->type = t;  conn->pcb.tcp = NULL;#if (DEFAULT_RAW_RECVMBOX_SIZE == DEFAULT_UDP_RECVMBOX_SIZE) && \    (DEFAULT_RAW_RECVMBOX_SIZE == DEFAULT_TCP_RECVMBOX_SIZE)  size = DEFAULT_RAW_RECVMBOX_SIZE;#else  switch(NETCONNTYPE_GROUP(t)) {#if LWIP_RAW  case NETCONN_RAW:    size = DEFAULT_RAW_RECVMBOX_SIZE;    break;#endif /* LWIP_RAW */#if LWIP_UDP  case NETCONN_UDP:    size = DEFAULT_UDP_RECVMBOX_SIZE;    break;#endif /* LWIP_UDP */#if LWIP_TCP  case NETCONN_TCP:    size = DEFAULT_TCP_RECVMBOX_SIZE;    break;#endif /* LWIP_TCP */  default:    LWIP_ASSERT("netconn_alloc: undefined netconn_type", 0);    break;  }#endif  if (sys_sem_new(&conn->op_completed, 0) != ERR_OK) {    memp_free(MEMP_NETCONN, conn);    return NULL;  }  if (sys_mbox_new(&conn->recvmbox, size) != ERR_OK) {    sys_sem_free(&conn->op_completed);    memp_free(MEMP_NETCONN, conn);    return NULL;  }#if LWIP_TCP  sys_mbox_set_invalid(&conn->acceptmbox);#endif  conn->state        = NETCONN_NONE;#if LWIP_SOCKET  /* initialize socket to -1 since 0 is a valid socket */  conn->socket       = -1;#endif /* LWIP_SOCKET */  conn->callback     = callback;#if LWIP_TCP  conn->current_msg  = NULL;  conn->write_offset = 0;#endif /* LWIP_TCP */#if LWIP_SO_RCVTIMEO  conn->recv_timeout = 0;#endif /* LWIP_SO_RCVTIMEO */#if LWIP_SO_RCVBUF  conn->recv_bufsize = RECV_BUFSIZE_DEFAULT;  conn->recv_avail   = 0;#endif /* LWIP_SO_RCVBUF */  conn->flags = 0;  return conn;}/** * Delete a netconn and all its resources. * The pcb is NOT freed (since we might not be in the right thread context do this). * * @param conn the netconn to free */voidnetconn_free(struct netconn *conn){  LWIP_ASSERT("PCB must be deallocated outside this function", conn->pcb.tcp == NULL);  LWIP_ASSERT("recvmbox must be deallocated before calling this function",    !sys_mbox_valid(&conn->recvmbox));#if LWIP_TCP  LWIP_ASSERT("acceptmbox must be deallocated before calling this function",    !sys_mbox_valid(&conn->acceptmbox));#endif /* LWIP_TCP */  sys_sem_free(&conn->op_completed);  sys_sem_set_invalid(&conn->op_completed);  memp_free(MEMP_NETCONN, conn);}/** * Delete rcvmbox and acceptmbox of a netconn and free the left-over data in * these mboxes * * @param conn the netconn to free * @bytes_drained bytes drained from recvmbox * @accepts_drained pending connections drained from acceptmbox */static voidnetconn_drain(struct netconn *conn){  void *mem;#if LWIP_TCP  struct pbuf *p;#endif /* LWIP_TCP */  /* This runs in tcpip_thread, so we don't need to lock against rx packets */  /* Delete and drain the recvmbox. */  if (sys_mbox_valid(&conn->recvmbox)) {    while (sys_mbox_tryfetch(&conn->recvmbox, &mem) != SYS_MBOX_EMPTY) {#if LWIP_TCP      if (conn->type == NETCONN_TCP) {        if(mem != NULL) {          p = (struct pbuf*)mem;          /* pcb might be set to NULL already by err_tcp() */          if (conn->pcb.tcp != NULL) {            tcp_recved(conn->pcb.tcp, p->tot_len);          }          pbuf_free(p);        }      } else#endif /* LWIP_TCP */      {        netbuf_delete((struct netbuf *)mem);      }    }    sys_mbox_free(&conn->recvmbox);    sys_mbox_set_invalid(&conn->recvmbox);  }  /* Delete and drain the acceptmbox. */#if LWIP_TCP  if (sys_mbox_valid(&conn->acceptmbox)) {    while (sys_mbox_tryfetch(&conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) {      struct netconn *newconn = (struct netconn *)mem;      /* Only tcp pcbs have an acceptmbox, so no need to check conn->type */      /* pcb might be set to NULL already by err_tcp() */      if (conn->pcb.tcp != NULL) {        tcp_accepted(conn->pcb.tcp);      }      /* drain recvmbox */      netconn_drain(newconn);      if (newconn->pcb.tcp != NULL) {        tcp_abort(newconn->pcb.tcp);        newconn->pcb.tcp = NULL;      }      netconn_free(newconn);    }    sys_mbox_free(&conn->acceptmbox);    sys_mbox_set_invalid(&conn->acceptmbox);  }#endif /* LWIP_TCP */}#if LWIP_TCP/** * Internal helper function to close a TCP netconn: since this sometimes * doesn't work at the first attempt, this function is called from multiple * places. * * @param conn the TCP netconn to close */static voiddo_close_internal(struct netconn *conn){  err_t err;  u8_t shut, shut_rx, shut_tx, close;  LWIP_ASSERT("invalid conn", (conn != NULL));  LWIP_ASSERT("this is for tcp netconns only", (conn->type == NETCONN_TCP));  LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE));  LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL));  LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL);  shut = conn->current_msg->msg.sd.shut;  shut_rx = shut & NETCONN_SHUT_RD;  shut_tx = shut & NETCONN_SHUT_WR;  /* shutting down both ends is the same as closing */  close = shut == NETCONN_SHUT_RDWR;  /* Set back some callback pointers */  if (close) {    tcp_arg(conn->pcb.tcp, NULL);  }  if (conn->pcb.tcp->state == LISTEN) {    tcp_accept(conn->pcb.tcp, NULL);  } else {    /* some callbacks have to be reset if tcp_close is not successful */    if (shut_rx) {      tcp_recv(conn->pcb.tcp, NULL);      tcp_accept(conn->pcb.tcp, NULL);    }    if (shut_tx) {      tcp_sent(conn->pcb.tcp, NULL);    }    if (close) {      tcp_poll(conn->pcb.tcp, NULL, 4);      tcp_err(conn->pcb.tcp, NULL);    }  }  /* Try to close the connection */  if (shut == NETCONN_SHUT_RDWR) {    err = tcp_close(conn->pcb.tcp);  } else {    err = tcp_shutdown(conn->pcb.tcp, shut & NETCONN_SHUT_RD, shut & NETCONN_SHUT_WR);  }  if (err == ERR_OK) {    /* Closing succeeded */    conn->current_msg->err = ERR_OK;    conn->current_msg = NULL;    conn->state = NETCONN_NONE;    /* Set back some callback pointers as conn is going away */    conn->pcb.tcp = NULL;    /* Trigger select() in socket layer. Make sure everybody notices activity       on the connection, error first! */    if (close) {      API_EVENT(conn, NETCONN_EVT_ERROR, 0);    }    if (shut_rx) {      API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);    }    if (shut_tx) {      API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);    }    /* wake up the application task */    sys_sem_signal(&conn->op_completed);  } else {    /* Closing failed, restore some of the callbacks */    /* Closing of listen pcb will never fail! */    LWIP_ASSERT("Closing a listen pcb may not fail!", (conn->pcb.tcp->state != LISTEN));    tcp_sent(conn->pcb.tcp, sent_tcp);    tcp_poll(conn->pcb.tcp, poll_tcp, 4);    tcp_err(conn->pcb.tcp, err_tcp);    tcp_arg(conn->pcb.tcp, conn);    /* don't restore recv callback: we don't want to receive any more data */  }  /* If closing didn't succeed, we get called again either     from poll_tcp or from sent_tcp */}#endif /* LWIP_TCP *//** * Delete the pcb inside a netconn. * Called from netconn_delete. * * @param msg the api_msg_msg pointing to the connection */voiddo_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("msg->conn->type == NETCONN_TCP", 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;        do_close_internal(msg->conn);        /* API_EVENT is called inside 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);  }}/** * Bind a pcb contained in a netconn * Called from netconn_bind. * * @param msg the api_msg_msg pointing to the connection and containing *            the IP address and port to bind to */voiddo_bind(struct api_msg_msg *msg){  if (ERR_IS_FATAL(msg->conn->last_err)) {    msg->err = msg->conn->last_err;  } else {    msg->err = ERR_VAL;    if (msg->conn->pcb.tcp != NULL) {      switch (NETCONNTYPE_GROUP(msg->conn->type)) {#if LWIP_RAW      case NETCONN_RAW:        msg->err = raw_bind(msg->conn->pcb.raw, msg->msg.bc.ipaddr);        break;#endif /* LWIP_RAW */#if LWIP_UDP      case NETCONN_UDP:        msg->err = udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);        break;#endif /* LWIP_UDP */#if LWIP_TCP      case NETCONN_TCP:        msg->err = tcp_bind(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port);        break;#endif /* LWIP_TCP */      default:        break;      }    }  }  TCPIP_APIMSG_ACK(msg);}#if LWIP_TCP/** * TCP callback function if a connection (opened by tcp_connect/do_connect) has * been established (or reset by the remote host). * * @see tcp.h (struct tcp_pcb.connected) for parameters and return values */static err_tdo_connected(void *arg, struct tcp_pcb *pcb, err_t err){  struct netconn *conn;  int was_blocking;  LWIP_UNUSED_ARG(pcb);  conn = (struct netconn *)arg;  if (conn == NULL) {    return ERR_VAL;  }  LWIP_ASSERT("conn->state == NETCONN_CONNECT", conn->state == NETCONN_CONNECT);  LWIP_ASSERT("(conn->current_msg != NULL) || conn->in_non_blocking_connect",    (conn->current_msg != NULL) || IN_NONBLOCKING_CONNECT(conn));  if (conn->current_msg != NULL) {    conn->current_msg->err = err;  }  if ((conn->type == NETCONN_TCP) && (err == ERR_OK)) {    setup_tcp(conn);  }  was_blocking = !IN_NONBLOCKING_CONNECT(conn);  SET_NONBLOCKING_CONNECT(conn, 0);  conn->current_msg = NULL;  conn->state = NETCONN_NONE;  if (!was_blocking) {    NETCONN_SET_SAFE_ERR(conn, ERR_OK);  }  API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);  if (was_blocking) {    sys_sem_signal(&conn->op_completed);  }  return ERR_OK;}#endif /* LWIP_TCP *//** * Connect a pcb contained inside a netconn * Called from netconn_connect. * * @param msg the api_msg_msg pointing to the connection and containing *            the IP address and port to connect to */voiddo_connect(struct api_msg_msg *msg){  if (msg->conn->pcb.tcp == NULL) {    /* This may happen when calling netconn_connect() a second time */    msg->err = ERR_CLSD;  } else {    switch (NETCONNTYPE_GROUP(msg->conn->type)) {#if LWIP_RAW  case NETCONN_RAW:    msg->err = raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr);    break;#endif /* LWIP_RAW */#if LWIP_UDP  case NETCONN_UDP:    msg->err = udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);    break;#endif /* LWIP_UDP */#if LWIP_TCP  case NETCONN_TCP:    /* Prevent connect while doing any other action. */    if (msg->conn->state != NETCONN_NONE) {      msg->err = ERR_ISCONN;    } else {      setup_tcp(msg->conn);      msg->err = tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr,        msg->msg.bc.port, do_connected);      if (msg->err == ERR_OK) {        u8_t non_blocking = netconn_is_nonblocking(msg->conn);        msg->conn->state = NETCONN_CONNECT;        SET_NONBLOCKING_CONNECT(msg->conn, non_blocking);        if (non_blocking) {          msg->err = ERR_INPROGRESS;        } else {          msg->conn->current_msg = msg;          /* sys_sem_signal() is called from do_connected (or err_tcp()),          * when the connection is established! */          return;        }      }    }    break;#endif /* LWIP_TCP */  default:    LWIP_ERROR("Invalid netconn type", 0, do{ msg->err = ERR_VAL; }while(0));    break;    }  }  sys_sem_signal(&msg->conn->op_completed);}/** * Connect a pcb contained inside a netconn * Only used for UDP netconns.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -