]> Zhao Yanbai Git Server - minix.git/commitdiff
libnetsock: use libchardriver 73/973/2
authorDavid van Moolenbroek <david@minix3.org>
Wed, 4 Sep 2013 15:42:36 +0000 (15:42 +0000)
committerLionel Sambuc <lionel@minix3.org>
Sat, 1 Mar 2014 08:04:51 +0000 (09:04 +0100)
Change-Id: Ia5b780cad0b0c636db9bd866c7223da0d38ef6ea

include/minix/netsock.h
lib/libnetsock/socket.c
servers/lwip/lwip.c

index 0c553e0660a72940b988c21fcaacc035e98d63c0..1a53813efa24172fa7759c06c65b8a41c3720b65 100644 (file)
@@ -118,7 +118,7 @@ int socket_open(devminor_t minor);
 
 extern struct socket socket[MAX_SOCKETS];
 
-void socket_request(message * m);
+void socket_request(message * m, int ipc_status);
 void mq_process(void);
 
 struct socket * get_unused_sock(void);
index 74d6482e27b824101d5aad797aadf453fab3b13c..912e94f15c9fbbb64d71a0f9bf3a06ba58e11b8a 100644 (file)
@@ -42,6 +42,30 @@ char * netsock_user_name = NULL;
 
 struct socket socket[MAX_SOCKETS];
 
+static int netsock_open(devminor_t minor, int access, endpoint_t user_endpt);
+static int netsock_close(devminor_t minor);
+static ssize_t netsock_read(devminor_t minor, u64_t position, endpoint_t endpt,
+       cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
+static ssize_t netsock_write(devminor_t minor, u64_t position,
+       endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags,
+       cdev_id_t id);
+static int netsock_ioctl(devminor_t minor, unsigned long request,
+       endpoint_t endpt, cp_grant_id_t grant, int flags,
+       endpoint_t user_endpt, cdev_id_t id);
+static int netsock_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id);
+static int netsock_select(devminor_t minor, unsigned int ops,
+       endpoint_t endpt);
+
+static struct chardriver netsock_tab = {
+       .cdr_open       = netsock_open,
+       .cdr_close      = netsock_close,
+       .cdr_read       = netsock_read,
+       .cdr_write      = netsock_write,
+       .cdr_ioctl      = netsock_ioctl,
+       .cdr_cancel     = netsock_cancel,
+       .cdr_select     = netsock_select
+};
+
 #define recv_q_alloc() debug_malloc(sizeof(struct recv_q))
 #define recv_q_free    debug_free
 
@@ -191,107 +215,30 @@ void sock_dequeue_data_all(struct socket * sock,
        sock->recv_data_size = 0;
 }
 
-static void set_reply_msg(message * m, int status)
-{
-       int proc, ref;
-
-       proc= m->USER_ENDPT;
-       ref= (int)m->IO_GRANT;
-
-       m->REP_ENDPT= proc;
-       m->REP_STATUS= status;
-       m->REP_IO_GRANT= ref;
-}
-
-static void send_reply_type(message * m, int type, int status)
-{
-       int result;
-
-       set_reply_msg(m, status);
-
-       m->m_type = type;
-       result = send(m->m_source, m);
-       if (result != OK)
-               netsock_panic("unable to send (err %d)", result);
-}
-
 void send_req_reply(struct sock_req * req, int status)
 {
-       message m;
-       int result;
-
        if (status == EDONTREPLY)
                return;
 
-       m.m_type = DEV_REVIVE;
-       m.REP_STATUS = status;
-       m.REP_ENDPT = req->endpt; /* FIXME: HACK */
-       m.REP_IO_GRANT = req->id;
-
-       result = send(req->endpt, &m);
-       if (result != OK)
-               netsock_panic("unable to send (err %d)", result);
-}
-
-static void send_reply(message * m, int status)
-{
-       debug_sock_print("status %d", status);
-       send_reply_type(m, DEV_REVIVE, status);
-}
-
-static void send_reply_open(message * m, int status)
-{
-       debug_sock_print("status %d", status);
-       send_reply_type(m, DEV_OPEN_REPL, status);
-}
-
-static void send_reply_close(message * m, int status)
-{
-       debug_sock_print("status %d", status);
-       send_reply_type(m, DEV_CLOSE_REPL, status);
-}
-
-static void sock_reply_select(struct socket * sock, endpoint_t endpt,
-       unsigned selops)
-{
-       int result;
-       message msg;
-
-       debug_sock_select_print("selops %d", selops);
-
-       msg.m_type = DEV_SEL_REPL1;
-       msg.DEV_MINOR = get_sock_num(sock);
-       msg.DEV_SEL_OPS = selops;
-
-       result = send(endpt, &msg);
-       if (result != OK)
-               netsock_panic("unable to send (err %d)", result);
+       chardriver_reply_task(req->endpt, req->id, status);
 }
 
 void sock_select_notify(struct socket * sock)
 {
-       int result;
-       message msg;
+       unsigned int ops;
 
        debug_sock_select_print("socket num %ld", get_sock_num(sock));
        assert(sock->select_ep != NONE);
 
-       msg.DEV_SEL_OPS = sock->ops->select_reply(sock);
-       if (msg.DEV_SEL_OPS == 0) {
+       ops = sock->ops->select_reply(sock);
+       if (ops == 0) {
                debug_sock_select_print("called from %p sflags 0x%x TXsz %d RXsz %d\n",
                                __builtin_return_address(0), sock->flags,
                                sock->buf_size, sock->recv_data_size);
                return;
        }
 
-       msg.m_type = DEV_SEL_REPL2;
-       msg.DEV_MINOR = get_sock_num(sock);
-
-       debug_sock_select_print("socket num %d select result 0x%x sent",
-                       msg.DEV_MINOR, msg.DEV_SEL_OPS);
-       result = send(sock->select_ep, &msg);
-       if (result != OK)
-               netsock_panic("unable to send (err %d)", result);
+       chardriver_reply_select(sock->select_ep, get_sock_num(sock), ops);
 
        sock_clear_select(sock);
        sock->select_ep = NONE;
@@ -342,119 +289,183 @@ static int socket_request_socket(struct socket * sock, struct sock_req * req)
        return r;
 }
 
-void socket_request(message * m)
+static int netsock_open(devminor_t minor, int UNUSED(access),
+       endpoint_t UNUSED(user_endpt))
 {
-       struct socket * sock;
+       return socket_open(minor);
+}
+
+static int netsock_close(devminor_t minor)
+{
+       struct socket *sock;
+
+       if (!(sock = get_sock(minor)))
+               return EINVAL;
+
+       if (sock->ops && sock->ops->close) {
+               sock->flags &= ~SOCK_FLG_OP_PENDING;
+
+               return sock->ops->close(sock);
+       } else
+               return EINVAL;
+}
+
+static int netsock_request(struct socket *sock, struct sock_req *req)
+{
+       char *o;
+
+       /*
+        * If an operation is pending (blocking operation) or writing is
+        * still going on and we're reading, suspend the new operation
+        */
+       if ((sock->flags & SOCK_FLG_OP_PENDING) ||
+                       (req->type == SOCK_REQ_READ &&
+                       sock->flags & SOCK_FLG_OP_WRITING)) {
+               if (sock->flags & SOCK_FLG_OP_READING)
+                       o = "READ";
+               else if (sock->flags & SOCK_FLG_OP_WRITING)
+                       o = "WRITE";
+               else
+                       o = "non R/W op";
+               debug_sock_print("socket %ld is busy by %s flgs 0x%x\n",
+                       get_sock_num(sock), o, sock->flags);
+
+               if (mq_enqueue(req) != 0) {
+                       debug_sock_print("Enqueuing suspended call failed");
+                       return ENOMEM;
+               }
+
+               return EDONTREPLY;
+       }
+
+       return socket_request_socket(sock, req);
+}
+
+static ssize_t netsock_read(devminor_t minor, u64_t UNUSED(position),
+       endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags,
+       cdev_id_t id)
+{
+       struct socket *sock;
        struct sock_req req;
+
+       if (!(sock = get_sock(minor)))
+               return EINVAL;
+
+       /* Build a request record for this request. */
+       req.type = SOCK_REQ_READ;
+       req.minor = minor;
+       req.endpt = endpt;
+       req.grant = grant;
+       req.size = size;
+       req.flags = flags;
+       req.id = id;
+
+       /* Process the request. */
+       return netsock_request(sock, &req);
+}
+
+static ssize_t netsock_write(devminor_t minor, u64_t UNUSED(position),
+       endpoint_t endpt, cp_grant_id_t grant, size_t size, int flags,
+       cdev_id_t id)
+{
+       struct socket *sock;
+       struct sock_req req;
+
+       if (!(sock = get_sock(minor)))
+               return EINVAL;
+
+       /* Build a request record for this request. */
+       req.type = SOCK_REQ_WRITE;
+       req.minor = minor;
+       req.endpt = endpt;
+       req.grant = grant;
+       req.size = size;
+       req.flags = flags;
+       req.id = id;
+
+       /* Process the request. */
+       return netsock_request(sock, &req);
+}
+
+static int netsock_ioctl(devminor_t minor, unsigned long request,
+       endpoint_t endpt, cp_grant_id_t grant, int flags,
+       endpoint_t UNUSED(user_endpt), cdev_id_t id)
+{
+       struct socket *sock;
+       struct sock_req req;
+
+       if (!(sock = get_sock(minor)))
+               return EINVAL;
+
+       /* Build a request record for this request. */
+       req.type = SOCK_REQ_IOCTL;
+       req.minor = minor;
+       req.req = request;
+       req.endpt = endpt;
+       req.grant = grant;
+       req.flags = flags;
+       req.id = id;
+
+       /* Process the request. */
+       return netsock_request(sock, &req);
+}
+
+static int netsock_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id)
+{
+       struct socket *sock;
+
+       if (!(sock = get_sock(minor)))
+               return EDONTREPLY;
+
+       debug_sock_print("socket num %ld", get_sock_num(sock));
+
+       /* Cancel the last operation in the queue */
+       if (mq_cancel(minor, endpt, id))
+               return EINTR;
+
+       /* Cancel any ongoing blocked read */
+       if ((sock->flags & SOCK_FLG_OP_PENDING) &&
+                       (sock->flags & SOCK_FLG_OP_READING) &&
+                       endpt == sock->req.endpt && id == sock->req.id) {
+               sock->flags &= ~SOCK_FLG_OP_PENDING;
+               return EINTR;
+       }
+
+       /* The request may not be found. This is OK. Do not reply. */
+       return EDONTREPLY;
+}
+
+static int netsock_select(devminor_t minor, unsigned int ops, endpoint_t endpt)
+{
+       struct socket *sock;
        int r;
 
+       /*
+        * Select is always executed immediately and is never suspended.
+        * Although, it sets actions which must be monitored
+        */
+       if (!(sock = get_sock(minor)))
+               return EBADF;
+
+       assert(sock->select_ep == NONE || sock->select_ep == endpt);
+
+       if (sock->ops && sock->ops->select) {
+               sock->select_ep = endpt;
+               r = sock->ops->select(sock, ops);
+               if (!sock_select_set(sock))
+                       sock->select_ep = NONE;
+       } else
+               r = EINVAL;
+
+       return r;
+}
+
+void socket_request(message * m, int ipc_status)
+{
        debug_sock_print("request %d", m->m_type);
-       switch (m->m_type) {
-       case DEV_OPEN:
-               r = socket_open(m->DEVICE);
-               send_reply_open(m, r);
-               return;
-       case DEV_CLOSE:
-               sock = get_sock(m->DEVICE);
-               if (sock->ops && sock->ops->close) {
-                       sock->flags &= ~SOCK_FLG_OP_PENDING;
-                       r = sock->ops->close(sock);
-               } else
-                       r = EINVAL;
-               send_reply_close(m, r);
-               return;
-       case DEV_READ_S:
-       case DEV_WRITE_S:
-       case DEV_IOCTL_S:
-               sock = get_sock(m->DEVICE);
-               if (!sock) {
-                       send_reply(m, EINVAL);
-                       return;
-               }
-               /* Build a request record for this request. */
-               req.minor = m->DEVICE;
-               req.endpt = m->m_source;
-               req.grant = (cp_grant_id_t) m->IO_GRANT;
-               req.id = (cdev_id_t) m->IO_GRANT;
-               req.flags = m->FLAGS;
-               switch (m->m_type) {
-               case DEV_READ_S:
-               case DEV_WRITE_S:
-                       req.type = (m->m_type == DEV_READ_S) ?
-                               SOCK_REQ_READ : SOCK_REQ_WRITE;
-                       req.size = m->COUNT;
-                       break;
-               case DEV_IOCTL_S:
-                       req.type = SOCK_REQ_IOCTL;
-                       req.req = m->REQUEST;
-                       break;
-               }
-               /*
-                * If an operation is pending (blocking operation) or writing is
-                * still going and we want to read, suspend the new operation
-                */
-               if ((sock->flags & SOCK_FLG_OP_PENDING) ||
-                               (m->m_type == DEV_READ_S &&
-                                sock->flags & SOCK_FLG_OP_WRITING)) {
-                       char * o = "\0";
-                       if (sock->flags & SOCK_FLG_OP_READING)
-                               o = "READ";
-                       else if (sock->flags & SOCK_FLG_OP_WRITING)
-                               o = "WRITE";
-                       else
-                               o = "non R/W op";
-                       debug_sock_print("socket %ld is busy by %s flgs 0x%x\n",
-                                       get_sock_num(sock), o, sock->flags);
-                       if (mq_enqueue(&req) != 0) {
-                               debug_sock_print("Enqueuing suspended "
-                                                       "call failed");
-                               send_reply(m, ENOMEM);
-                       }
-                       return;
-               }
-               sock->req = req;
-               r = socket_request_socket(sock, &req);
-               send_req_reply(&req, r);
-               return;
-       case CANCEL:
-               sock = get_sock(m->DEVICE);
-               printf("socket num %ld\n", get_sock_num(sock));
-               debug_sock_print("socket num %ld", get_sock_num(sock));
-               /* Cancel the last operation in the queue */
-               if (mq_cancel(m->DEVICE, m->m_source,
-                               (cdev_id_t) m->IO_GRANT)) {
-                       send_reply(m, EINTR);
-               /* ... or a blocked read */
-               } else if (sock->flags & SOCK_FLG_OP_PENDING &&
-                               sock->flags & SOCK_FLG_OP_READING) {
-                       sock->flags &= ~SOCK_FLG_OP_PENDING;
-                       send_reply(m, EINTR);
-               }
-               /* The request may not be found. This is OK. Do not reply. */
-               return;
-       case DEV_SELECT:
-               /*
-                * Select is always executed immediately and is never suspended.
-                * Although, it sets actions which must be monitored
-                */
-               sock = get_sock(m->DEVICE);
-               assert(sock->select_ep == NONE || sock->select_ep == m->m_source);
-
-               if (sock->ops && sock->ops->select) {
-                       sock->select_ep = m->m_source;
-                       r = sock->ops->select(sock, m->DEV_SEL_OPS);
-                       if (!sock_select_set(sock))
-                               sock->select_ep = NONE;
-               } else
-                       r = EINVAL;
 
-               sock_reply_select(sock, m->m_source, r);
-               return;
-       default:
-               netsock_error("unknown message from VFS, type %d\n",
-                                                       m->m_type);
-       }
-       send_reply(m, EGENERIC);
+       /* Let the chardriver library decode the request for us. */
+       chardriver_process(&netsock_tab, m, ipc_status);
 }
 
 void mq_process(void)
index 8f95b5f425b57b50c623d998f7a0119370cb36b2..c7f75a85d7501d88e8a7f45b6a3a121d7eaffa8c 100644 (file)
@@ -271,7 +271,7 @@ int main(__unused int argc, __unused char ** argv)
                }
 
                if (m.m_source == VFS_PROC_NR)
-                       socket_request(&m);
+                       socket_request(&m, ipc_status);
                else if (is_ipc_notify(ipc_status)) {
                        switch (m.m_source) {
                        case CLOCK: