예제 #1
0
파일: api_msg.c 프로젝트: comrid1987/jb3500
/**
 * Close a TCP pcb contained in a netconn
 * Called from netconn_close
 *
 * @param msg the api_msg_msg pointing to the connection
 */
void
do_close(struct api_msg_msg *msg)
{
#if LWIP_TCP
    /* @todo: abort running write/connect? */
    if ((msg->conn->state != NETCONN_NONE) && (msg->conn->state != NETCONN_LISTEN)) {
        /* this only happens for TCP netconns */
        LWIP_ASSERT("msg->conn->type == NETCONN_TCP", msg->conn->type == NETCONN_TCP);
        msg->err = ERR_INPROGRESS;
    } else if ((msg->conn->pcb.tcp != NULL) && (msg->conn->type == NETCONN_TCP)) {
        if ((msg->msg.sd.shut != NETCONN_SHUT_RDWR) && (msg->conn->state == NETCONN_LISTEN)) {
            /* LISTEN doesn't support half shutdown */
            msg->err = ERR_CONN;
        } else {
            if (msg->msg.sd.shut & NETCONN_SHUT_RD) {
                /* Drain and delete mboxes */
                netconn_drain(msg->conn);
            }
            LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL &&
                        msg->conn->write_offset == 0);
            msg->conn->state = NETCONN_CLOSE;
            msg->conn->current_msg = msg;
            do_close_internal(msg->conn);
            /* for tcp netconns, do_close_internal ACKs the message */
            return;
        }
    } else
#endif /* LWIP_TCP */
    {
        msg->err = ERR_VAL;
    }
    sys_sem_signal(&msg->conn->op_completed);
}
예제 #2
0
파일: api_msg.c 프로젝트: mtharp/lwip
/**
 * 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);
  }
}
예제 #3
0
파일: api_msg.c 프로젝트: comrid1987/jb3500
/**
 * 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 void
netconn_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 */
}