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

📄 linux-tcpip.c

📁 非常经典的一个分布式系统
💻 C
📖 第 1 页 / 共 2 页
字号:
        unsigned long  then;        struct timeval tv;        LASSERT (nob > 0);        LASSERT (ticks > 0);        for (;;) {                struct iovec  iov = {                        .iov_base = buffer,                        .iov_len  = nob                };                struct msghdr msg = {                        .msg_name       = NULL,                        .msg_namelen    = 0,                        .msg_iov        = &iov,                        .msg_iovlen     = 1,                        .msg_control    = NULL,                        .msg_controllen = 0,                        .msg_flags      = 0                };                /* Set receive timeout to remaining time */                tv = (struct timeval) {                        .tv_sec = ticks / HZ,                        .tv_usec = ((ticks % HZ) * 1000000) / HZ                };                set_fs(KERNEL_DS);                rc = sock_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,                                     (char *)&tv, sizeof(tv));                set_fs(oldmm);                if (rc != 0) {                        CERROR("Can't set socket recv timeout %ld.%06d: %d\n",                               (long)tv.tv_sec, (int)tv.tv_usec, rc);                        return rc;                }                set_fs(KERNEL_DS);                then = jiffies;                rc = sock_recvmsg(sock, &msg, iov.iov_len, 0);                ticks -= jiffies - then;                set_fs(oldmm);                if (rc < 0)                        return rc;                if (rc == 0)                        return -ECONNRESET;                buffer = ((char *)buffer) + rc;                nob -= rc;                if (nob == 0)                        return 0;                if (ticks <= 0)                        return -ETIMEDOUT;        }}EXPORT_SYMBOL(libcfs_sock_read);static intlibcfs_sock_create (struct socket **sockp, int *fatal,                    __u32 local_ip, int local_port){        struct sockaddr_in  locaddr;        struct socket      *sock;        int                 rc;        int                 option;        mm_segment_t        oldmm = get_fs();        /* All errors are fatal except bind failure if the port is in use */        *fatal = 1;        rc = sock_create (PF_INET, SOCK_STREAM, 0, &sock);        *sockp = sock;        if (rc != 0) {                CERROR ("Can't create socket: %d\n", rc);                return (rc);        }        set_fs (KERNEL_DS);        option = 1;        rc = sock_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,                             (char *)&option, sizeof (option));        set_fs (oldmm);        if (rc != 0) {                CERROR("Can't set SO_REUSEADDR for socket: %d\n", rc);                goto failed;        }        if (local_ip != 0 || local_port != 0) {                memset(&locaddr, 0, sizeof(locaddr));                locaddr.sin_family = AF_INET;                locaddr.sin_port = htons(local_port);                locaddr.sin_addr.s_addr = (local_ip == 0) ?                                          INADDR_ANY : htonl(local_ip);                rc = sock->ops->bind(sock, (struct sockaddr *)&locaddr,                                     sizeof(locaddr));                if (rc == -EADDRINUSE) {                        CDEBUG(D_NET, "Port %d already in use\n", local_port);                        *fatal = 0;                        goto failed;                }                if (rc != 0) {                        CERROR("Error trying to bind to port %d: %d\n",                               local_port, rc);                        goto failed;                }        }        return 0; failed:        sock_release(sock);        return rc;}intlibcfs_sock_setbuf (struct socket *sock, int txbufsize, int rxbufsize){        mm_segment_t        oldmm = get_fs();        int                 option;        int                 rc;        if (txbufsize != 0) {                option = txbufsize;                set_fs (KERNEL_DS);                rc = sock_setsockopt(sock, SOL_SOCKET, SO_SNDBUF,                                     (char *)&option, sizeof (option));                set_fs (oldmm);                if (rc != 0) {                        CERROR ("Can't set send buffer %d: %d\n",                                option, rc);                        return (rc);                }        }        if (rxbufsize != 0) {                option = rxbufsize;                set_fs (KERNEL_DS);                rc = sock_setsockopt (sock, SOL_SOCKET, SO_RCVBUF,                                      (char *)&option, sizeof (option));                set_fs (oldmm);                if (rc != 0) {                        CERROR ("Can't set receive buffer %d: %d\n",                                option, rc);                        return (rc);                }        }        return 0;}EXPORT_SYMBOL(libcfs_sock_setbuf);intlibcfs_sock_getaddr (struct socket *sock, int remote, __u32 *ip, int *port){        struct sockaddr_in sin;        int                len = sizeof (sin);        int                rc;        rc = sock->ops->getname (sock, (struct sockaddr *)&sin, &len,                                 remote ? 2 : 0);        if (rc != 0) {                CERROR ("Error %d getting sock %s IP/port\n",                        rc, remote ? "peer" : "local");                return rc;        }        if (ip != NULL)                *ip = ntohl (sin.sin_addr.s_addr);        if (port != NULL)                *port = ntohs (sin.sin_port);        return 0;}EXPORT_SYMBOL(libcfs_sock_getaddr);intlibcfs_sock_getbuf (struct socket *sock, int *txbufsize, int *rxbufsize){        if (txbufsize != NULL) {                *txbufsize = sock->sk->sk_sndbuf;        }        if (rxbufsize != NULL) {                *rxbufsize = sock->sk->sk_rcvbuf;        }        return 0;}EXPORT_SYMBOL(libcfs_sock_getbuf);intlibcfs_sock_listen (struct socket **sockp,                    __u32 local_ip, int local_port, int backlog){        int      fatal;        int      rc;        rc = libcfs_sock_create(sockp, &fatal, local_ip, local_port);        if (rc != 0) {                if (!fatal)                        CERROR("Can't create socket: port %d already in use\n",                               local_port);                return rc;        }        rc = (*sockp)->ops->listen(*sockp, backlog);        if (rc == 0)                return 0;        CERROR("Can't set listen backlog %d: %d\n", backlog, rc);        sock_release(*sockp);        return rc;}EXPORT_SYMBOL(libcfs_sock_listen);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)int sock_create_lite(int family, int type, int protocol, struct socket **res){        struct socket *sock;        sock = sock_alloc();        if (sock == NULL)                 return -ENOMEM;        sock->type = type;        *res = sock;        return 0;}#endifintlibcfs_sock_accept (struct socket **newsockp, struct socket *sock){        wait_queue_t   wait;        struct socket *newsock;        int            rc;        init_waitqueue_entry(&wait, current);        /* XXX this should add a ref to sock->ops->owner, if         * TCP could be a module */        rc = sock_create_lite(PF_PACKET, sock->type, IPPROTO_TCP, &newsock);        if (rc) {                CERROR("Can't allocate socket\n");                return rc;        }        newsock->ops = sock->ops;        set_current_state(TASK_INTERRUPTIBLE);        add_wait_queue(sock->sk->sk_sleep, &wait);        rc = sock->ops->accept(sock, newsock, O_NONBLOCK);        if (rc == -EAGAIN) {                /* Nothing ready, so wait for activity */                schedule();                rc = sock->ops->accept(sock, newsock, O_NONBLOCK);        }        remove_wait_queue(sock->sk->sk_sleep, &wait);        set_current_state(TASK_RUNNING);        if (rc != 0)                goto failed;        *newsockp = newsock;        return 0; failed:        sock_release(newsock);        return rc;}EXPORT_SYMBOL(libcfs_sock_accept);voidlibcfs_sock_abort_accept (struct socket *sock){        wake_up_all(sock->sk->sk_sleep);}EXPORT_SYMBOL(libcfs_sock_abort_accept);intlibcfs_sock_connect (struct socket **sockp, int *fatal,                     __u32 local_ip, int local_port,                     __u32 peer_ip, int peer_port){        struct sockaddr_in  srvaddr;        int                 rc;        rc = libcfs_sock_create(sockp, fatal, local_ip, local_port);        if (rc != 0)                return rc;        memset (&srvaddr, 0, sizeof (srvaddr));        srvaddr.sin_family = AF_INET;        srvaddr.sin_port = htons(peer_port);        srvaddr.sin_addr.s_addr = htonl(peer_ip);        rc = (*sockp)->ops->connect(*sockp,                                    (struct sockaddr *)&srvaddr, sizeof(srvaddr),                                    0);        if (rc == 0)                return 0;        /* EADDRNOTAVAIL probably means we're already connected to the same         * peer/port on the same local port on a differently typed         * connection.  Let our caller retry with a different local         * port... */        *fatal = !(rc == -EADDRNOTAVAIL);        CDEBUG(*fatal ? D_NETERROR : D_NET,               "Error %d connecting %u.%u.%u.%u/%d -> %u.%u.%u.%u/%d\n", rc,               HIPQUAD(local_ip), local_port, HIPQUAD(peer_ip), peer_port);        sock_release(*sockp);        return rc;}EXPORT_SYMBOL(libcfs_sock_connect);voidlibcfs_sock_release (struct socket *sock){        sock_release(sock);}EXPORT_SYMBOL(libcfs_sock_release);

⌨️ 快捷键说明

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