doc: final revise of the document
[p2p-kernel-protocol.git] / module / p2pkp_sock.c
index d72fdb3..19d29d5 100644 (file)
@@ -130,6 +130,10 @@ static int p2pkp_release(struct socket *sock)
        sock->sk = NULL;
 
        p2pkp_destroy_udp_sock(ps->net_sock);
+       if (ps->file) {
+               p2pkp_close_file(ps->file);
+               ps->file = 0;
+       }
        
        sock_put(sk);
        DEBUG("Released the socket");
@@ -137,8 +141,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 +202,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;
@@ -203,25 +227,29 @@ static int p2pkp_sendmsg(struct kiocb *iocb, struct socket *sock,
        lock_sock(sk);
        if (!(sock->state & SS_CONNECTED)) {
                ERROR("unconnected socket");
-               err = -ECONNREFUSED;
-               goto release;
+               release_sock(sk);
+               return -ECONNREFUSED;
        }
        release_sock(sk);
 
        /* 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;
                }
+               ps->file = file;
                DEBUG("opened file %s", file_name);
                for (;;) {
                        bytes_read = p2pkp_read_from_file(file, ps->buffer, ps->buffer_len);
                        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 +260,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);
                }
@@ -246,19 +275,59 @@ out_conn:
 out_close:
 
                p2pkp_close_file(file);
+               ps->file = 0;
        }
 
-
        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 = 0;
+       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;
+       }
+       ps->file = file;
+
+       lock_sock(sk);
+       /* TODO keep connections */
+       do {
+               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 != -ERESTARTSYS) {
+                       ERROR("cannot read data: %d", bytes_read);
+                       err = -ENXIO;
+               }
+               DEBUG("wrote %d", bytes_written);
+       } while (bytes_read < ps->buffer_len);
+
+       release_sock(sk);
+       p2pkp_close_file(file);
+       ps->file = 0;
+
+       return err ? err : bytes_written;
+}
 
 
 static int p2pkp_create(struct net *net, struct socket *sock, int protocol,
@@ -318,5 +387,3 @@ error:
                sock_put(sk);
        return err;
 }
-
-