sendfile: added server implementation
[p2p-kernel-protocol.git] / module / p2pkp_sock.c
index d72fdb3..06862e3 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)
@@ -232,13 +255,14 @@ static int p2pkp_sendmsg(struct kiocb *iocb, struct socket *sock,
                        list_for_each(pos, &ps->conn_list) {
                                        
                                conn = list_entry(pos, struct p2pkp_conn_info, list);
-                               err = p2pkp_msgsend(ps->net_sock,
-                                               &conn->sin, ps->buffer, ps->buffer_len);
+                               err = p2pkp_msgsend(ps->net_sock, &conn->sin,
+                                               ps->buffer, bytes_read);
                                if (err < 0) {
                                        ERROR("can't send first message");
                                        goto out_conn;
                                }
                        }
+                       files_no++;
 out_conn:
                        release_sock(sk);
                }
@@ -248,17 +272,53 @@ 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);
+       DEBUG("XXX: received %d bytes\n", bytes_read);
+       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 +378,3 @@ error:
                sock_put(sk);
        return err;
 }
-
-