From e66f5918ff3a9448be9deec760600ff5f48111f0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?R=C4=83zvan=20Crainea?= Date: Sun, 27 May 2012 20:48:19 +0300 Subject: [PATCH] module: added support for receiving files from peers --- module/p2pkp.c | 40 ------------------------ module/p2pkp_file.c | 43 +++++++++++++++++++++++++- module/p2pkp_file.h | 2 ++ module/p2pkp_net.c | 23 ++++++++++++++ module/p2pkp_net.h | 1 + module/p2pkp_sock.c | 75 +++++++++++++++++++++++++++++++++++++++------ module/p2pkp_sock.h | 1 + 7 files changed, 135 insertions(+), 50 deletions(-) diff --git a/module/p2pkp.c b/module/p2pkp.c index 5561991..66ef1c1 100644 --- a/module/p2pkp.c +++ b/module/p2pkp.c @@ -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) diff --git a/module/p2pkp_file.c b/module/p2pkp_file.c index 48dc67c..2d206a4 100644 --- a/module/p2pkp_file.c +++ b/module/p2pkp_file.c @@ -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; diff --git a/module/p2pkp_file.h b/module/p2pkp_file.h index f98e32f..96fe93b 100644 --- a/module/p2pkp_file.h +++ b/module/p2pkp_file.h @@ -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_ */ diff --git a/module/p2pkp_net.c b/module/p2pkp_net.c index c178a71..19e7181 100644 --- a/module/p2pkp_net.c +++ b/module/p2pkp_net.c @@ -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) { diff --git a/module/p2pkp_net.h b/module/p2pkp_net.h index dd43124..87d74ce 100644 --- a/module/p2pkp_net.h +++ b/module/p2pkp_net.h @@ -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_ */ diff --git a/module/p2pkp_sock.c b/module/p2pkp_sock.c index d72fdb3..3c362a4 100644 --- a/module/p2pkp_sock.c +++ b/module/p2pkp_sock.c @@ -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; } - - diff --git a/module/p2pkp_sock.h b/module/p2pkp_sock.h index 96d25aa..ae5e78a 100644 --- a/module/p2pkp_sock.h +++ b/module/p2pkp_sock.h @@ -4,6 +4,7 @@ #include #define P2PKP_DEFAULT_BUF_LEN 256 +#define P2PKP_DEFAULT_MODE 0644 struct p2pkp_conn_info { struct sockaddr_in sin; -- 2.20.1