module: added support for receiving files from peers
authorRăzvan Crainea <razvan.crainea@gmail.com>
Sun, 27 May 2012 17:48:19 +0000 (20:48 +0300)
committerRăzvan Crainea <razvan.crainea@gmail.com>
Sun, 27 May 2012 17:48:19 +0000 (20:48 +0300)
module/p2pkp.c
module/p2pkp_file.c
module/p2pkp_file.h
module/p2pkp_net.c
module/p2pkp_net.h
module/p2pkp_sock.c
module/p2pkp_sock.h

index 5561991..66ef1c1 100644 (file)
@@ -18,51 +18,11 @@ MODULE_LICENSE("GPL");
 
 int __init p2pkp_sock_init(void)
 {
-       //int bytes_read;
-       //struct file *file = NULL;
-
-#if 0
-       /* address to bind on */
-       struct sockaddr_in addr = {
-               .sin_family     = AF_INET,
-               .sin_port       = htons(P2PKP_LOCAL_PORT),
-               .sin_addr       = { htonl(INADDR_LOOPBACK) }
-       };
-       int addrlen = sizeof(addr);
-#endif
-
        if (p2pkp_register_protocol() < 0) {
                ERROR("error while registering socket operations");
                return -1;
        }
        return 0;
-
-#if 0
-       /* bind socket to loopback on port P2PKP_LOCAL_PORT */
-       err = sock->ops->bind(sock, (struct sockaddr *) &addr, addrlen);
-       if (err < 0) {
-               ERROR("can't bind socket\n");
-               goto out_release;
-       }
-
-       /* send first message */
-       err = p2pkp_msgsend(sock, P2PKP_REMOTE_PORT1);
-       if (err < 0) {
-               ERROR("can't send first message\n");
-               goto out_release;
-       }
-
-       /* send second message */
-       err = p2pkp_msgsend(sock, P2PKP_REMOTE_PORT1);
-       if (err < 0) {
-               ERROR("can't send second message\n");
-               goto out_release;
-       }
-
-out_release:
-       /* cleanup socket */
-       sock_release(sock);
-#endif
 }
 
 void __exit p2pkp_sock_exit(void)
index 48dc67c..2d206a4 100644 (file)
@@ -11,18 +11,59 @@ struct file* p2pkp_open_file_read(const char *filename)
        return IS_ERR_OR_NULL(file) ? NULL : file;
 }
 
+struct file* p2pkp_open_file_write(const char *filename, mode_t mode)
+{
+       struct file * file;
+       file = filp_open(filename, O_CREAT|O_TRUNC, mode);
+       return IS_ERR_OR_NULL(file) ? NULL : file;
+}
+
 void p2pkp_close_file(struct file *file)
 {
        filp_close(file,NULL);
 }
 
+int p2pkp_write_in_file(struct file *file, char *buffer, int len)
+{
+       // Create variables
+       int bytes_written, ret;
+       mm_segment_t fs;
+
+       if(file == NULL) {
+               ERROR("filp_open error!!");
+               return -EINVAL;
+       }
+       DEBUG("Changinig segment descriptor");
+       // Get current segment descriptor
+       fs = get_fs();
+       // Set segment descriptor associated to kernel space
+       set_fs(get_ds());
+       DEBUG("Changed segment descriptor - buffer is %p", buffer);
+
+       bytes_written = 0;
+       do {
+               ret = file->f_op->write(file, buffer + bytes_written, len, &file->f_pos);
+               if (ret < 0) {
+                       ERROR("error while reading from file");
+                       break;
+               }
+               len -= ret;
+               bytes_written += ret;
+       } while (len > 0);
+
+       set_fs(fs);
+
+       return ret < 0 ? ret : bytes_written;
+}
+
+
+
 int p2pkp_read_from_file(struct file *file, char *buffer, int len)
 {
        // Create variables
        int read_bytes, offset;
        mm_segment_t fs;
 
-       // To see in /var/log/messages that the module is operating
        if(file == NULL) {
                ERROR("filp_open error!!");
                return -EINVAL;
index f98e32f..96fe93b 100644 (file)
@@ -3,7 +3,9 @@
 
 
 struct file* p2pkp_open_file_read(const char *filename);
+struct file* p2pkp_open_file_write(const char *filename, mode_t mode);
 void p2pkp_close_file(struct file *file);
 int p2pkp_read_from_file(struct file *file, char *buffer, int len);
+int p2pkp_write_in_file(struct file *file, char *buffer, int len);
 
 #endif /* _P2PKP_FILE_H_ */
index c178a71..19e7181 100644 (file)
@@ -27,6 +27,29 @@ int p2pkp_msgsend(struct socket *s, struct sockaddr_in *sin, char *buffer, int l
        return kernel_sendmsg(s, &msg, (struct kvec *) msg.msg_iov, 1, len);
 }
 
+/* receive datagram */
+int p2pkp_msgrecv(struct socket *s, struct sockaddr_in *sin, char *buffer, int len)
+{
+       /* message */
+       struct msghdr msg;
+       struct iovec iov;
+
+       /* build message */
+       iov.iov_base = buffer;
+       iov.iov_len = len;
+       msg.msg_name = sin;
+       msg.msg_namelen = sizeof(struct sockaddr_in);
+       msg.msg_iov = &iov;
+       msg.msg_iovlen = 1;
+       msg.msg_control = NULL;
+       msg.msg_controllen = 0;
+       msg.msg_flags = 0;
+
+       /* send the message down the socket */
+       return kernel_recvmsg(s, &msg, (struct kvec *) msg.msg_iov, 1, len, 0);
+}
+
+
 
 int p2pkp_create_udp_sock(struct socket **sock)
 {
index dd43124..87d74ce 100644 (file)
@@ -8,5 +8,6 @@
 int p2pkp_create_udp_sock(struct socket **sock);
 void p2pkp_destroy_udp_sock(struct socket *sock);
 int p2pkp_msgsend(struct socket *s, struct sockaddr_in *sin, char *buffer, int len);
+int p2pkp_msgrecv(struct socket *s, struct sockaddr_in *sin, char *buffer, int len);
 
 #endif /* _P2PKP_NET_H_ */
index d72fdb3..3c362a4 100644 (file)
@@ -137,8 +137,28 @@ static int p2pkp_release(struct socket *sock)
 }
 
 static int p2pkp_bind(struct socket *sock, struct sockaddr *myaddr,
-               int sockaddr_len){return 0;}
+               int sockaddr_len)
+{
+       struct sock *sk = sock->sk;
+       struct p2pkp_sock *ps = sock2p2pkp(sk);
+       struct sockaddr_in *sin = (struct sockaddr_in *)myaddr;
+       int err = 0;
+
+       if (!sock || !myaddr || sockaddr_len != sizeof(struct sockaddr_in) ||
+                       sin->sin_family != AF_INET) {
+               ERROR("invalid parameters for bind");
+               return -EINVAL;
+       }
+
+       lock_sock(sk);
+       err = ps->net_sock->ops->bind(ps->net_sock, myaddr, sockaddr_len);
+       if (err < 0) {
+               ERROR("can't bind socket");
+       }
+       release_sock(sk);
 
+       return err;
+}
 
 static int p2pkp_connect(struct socket *sock, struct sockaddr *vaddr,
                int sockaddr_len, int flags)
@@ -178,8 +198,8 @@ static int p2pkp_connect(struct socket *sock, struct sockaddr *vaddr,
 static int p2pkp_sendmsg(struct kiocb *iocb, struct socket *sock,
                struct msghdr *m, size_t total_len)
 {
-       int err = -ENXIO;
-       int f_index, bytes_read;
+       int err = 0;
+       int f_index, bytes_read, files_no = 0;
        struct sock *sk = sock->sk;
        struct p2pkp_sock *ps = sock2p2pkp(sk);
        struct sockaddr_in *sin = (struct sockaddr_in *)m->msg_name;
@@ -210,10 +230,12 @@ static int p2pkp_sendmsg(struct kiocb *iocb, struct socket *sock,
 
        /* check if the file exists */
        for (f_index = 0; f_index < m->msg_iovlen; f_index++) {
+               err = 0;
                file_name = (char *)m->msg_iov[f_index].iov_base;
                file = p2pkp_open_file_read(file_name);
                if (!file) {
                        ERROR("cannot open file %s\n", file_name);
+                       err = -ENOENT;
                        continue;
                }
                DEBUG("opened file %s", file_name);
@@ -222,6 +244,7 @@ static int p2pkp_sendmsg(struct kiocb *iocb, struct socket *sock,
                        DEBUG("read %d bytes from file", bytes_read);
                        if (bytes_read < 0) {
                                ERROR("cannot read from file");
+                               err = bytes_read;
                                goto out_close;
                        }
                        if (bytes_read == 0)
@@ -239,6 +262,7 @@ static int p2pkp_sendmsg(struct kiocb *iocb, struct socket *sock,
                                        goto out_conn;
                                }
                        }
+                       files_no++;
 out_conn:
                        release_sock(sk);
                }
@@ -248,17 +272,52 @@ out_close:
                p2pkp_close_file(file);
        }
 
-
        DEBUG("Sending completed successfully");
-       err = 0;
 release:
        release_sock(sk);
-       return err;
+       return err ? err : files_no;
 }
 
 
 static int p2pkp_recvmsg(struct kiocb *iocb, struct socket *sock,
-               struct msghdr *m, size_t total_len, int flags){return 0;}
+               struct msghdr *m, size_t total_len, int flags)
+{
+       int err = -ENXIO;
+       int bytes_read, bytes_written;
+       struct sock *sk = sock->sk;
+       struct p2pkp_sock *ps = sock2p2pkp(sk);
+       struct sockaddr_in *sin = (struct sockaddr_in *)m->msg_name;
+       struct file * file;
+       char *file_name = (char *)m->msg_iov[0].iov_base;
+       mode_t mode = P2PKP_DEFAULT_MODE;
+
+       /* first try to get some files */
+       if (!sock || !m || !file_name) {
+               ERROR("invalid socket parameters");
+               return -EINVAL;
+       }
+
+       file = p2pkp_open_file_write(file_name, mode);
+       if (!file) {
+               ERROR("cannot open file %s\n", file_name);
+               return -ENOENT;
+       }
+
+       lock_sock(sk);
+       /* TODO keep connections */
+       bytes_read = p2pkp_msgrecv(ps->net_sock, sin, ps->buffer, ps->buffer_len);
+       if (bytes_read > 0) {
+               bytes_written = p2pkp_write_in_file(file, ps->buffer, bytes_read);
+               err = 0;
+       } else if (bytes_read < 0) {
+               ERROR("cannot read data");
+               err = -ENXIO;
+       }
+       release_sock(sk);
+       p2pkp_close_file(file);
+
+       return err ? err : bytes_written;
+}
 
 
 static int p2pkp_create(struct net *net, struct socket *sock, int protocol,
@@ -318,5 +377,3 @@ error:
                sock_put(sk);
        return err;
 }
-
-
index 96d25aa..ae5e78a 100644 (file)
@@ -4,6 +4,7 @@
 #include <net/sock.h>
 
 #define P2PKP_DEFAULT_BUF_LEN  256
+#define P2PKP_DEFAULT_MODE             0644
 
 struct p2pkp_conn_info {
        struct sockaddr_in sin;