module: added support for multiple USERSPACE receivers
authorRăzvan Crainea <razvan.crainea@gmail.com>
Sun, 27 May 2012 15:22:45 +0000 (18:22 +0300)
committerRăzvan Crainea <razvan.crainea@gmail.com>
Sun, 27 May 2012 15:22:45 +0000 (18:22 +0300)
test: added testing program

18 files changed:
module/Kbuild
module/p2pkp.c [new file with mode: 0644]
module/p2pkp.h [new file with mode: 0644]
module/p2pkp_debug.h [new file with mode: 0644]
module/p2pkp_file.c [new file with mode: 0644]
module/p2pkp_file.h [new file with mode: 0644]
module/p2pkp_net.c [new file with mode: 0644]
module/p2pkp_net.h [new file with mode: 0644]
module/p2pkp_sock.c [new file with mode: 0644]
module/p2pkp_sock.h [new file with mode: 0644]
module/p2psp.c [deleted file]
module/test.sh [deleted file]
test/client/Makefile [new file with mode: 0644]
test/client/client [new file with mode: 0755]
test/client/client.c [new file with mode: 0644]
test/client/p2pkp.h [new file with mode: 0644]
test/client/test.sh [new file with mode: 0755]
test/client/test_file [new file with mode: 0644]

index 1934d9d..1b5fb8e 100644 (file)
@@ -1,3 +1,4 @@
 EXTRA_CFLAGS = -Wall -g
 
-obj-m        = p2psp.o
+obj-m = af_p2pkp.o
+af_p2pkp-y = p2pkp.o p2pkp_sock.o p2pkp_file.o p2pkp_net.o
diff --git a/module/p2pkp.c b/module/p2pkp.c
new file mode 100644 (file)
index 0000000..5561991
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Peer to Peer Kernel Protocol
+ *
+ * Răzvan Crainea
+ * Tudor Cazangiu
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include "p2pkp_sock.h"
+#include "p2pkp_debug.h"
+
+MODULE_DESCRIPTION("P2P Kernel Protocol");
+MODULE_AUTHOR("Razvan Crainea and Tudor Cazangiu");
+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)
+{
+       /* cleanup socket */
+       p2pkp_unregister_protocol();
+}
+
+module_init(p2pkp_sock_init);
+module_exit(p2pkp_sock_exit);
diff --git a/module/p2pkp.h b/module/p2pkp.h
new file mode 100644 (file)
index 0000000..f18d258
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _P2PKP_H_
+#define _P2PKP_H_
+
+#define AF_P2PKP               19
+#define PF_P2PKP               AF_P2PKP
+
+#endif /* _P2PKP_H_ */
diff --git a/module/p2pkp_debug.h b/module/p2pkp_debug.h
new file mode 100644 (file)
index 0000000..2b8e944
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef _P2PKP_DEBUG_H_
+#define _P2PKP_DEBUG_H_
+
+//#include "linux/kernel.h"
+
+#ifndef P2PKP_DEBUG
+ /* uncomment to turn debugging off */
+ #define P2PKP_DEBUG   yes
+#endif
+
+#ifdef P2PKP_DEBUG
+#define DEBUG(format, args...)                                 \
+       do {                                    \
+               printk(KERN_DEBUG "[%s:%d] " format "\n", __func__, __LINE__, ## args); \
+       } while (0)
+#else
+#define LOG(s)                                 \
+       do {} while (0)
+#endif
+
+/* p2pkp error func */
+#define ERROR(format, args...) \
+       do {                                    \
+               printk(KERN_ERR "[%s:%d] " format "\n", __func__, __LINE__, ## args); \
+       } while (0)
+
+#define print_sock_address(addr)               \
+       do {                                    \
+               printk(LOG_DEBUG "connection established to "   \
+                               NIPQUAD_FMT ":%d\n",            \
+                               NIPQUAD(addr.sin_addr.s_addr),  \
+                               ntohs(addr.sin_port));          \
+       } while (0)
+
+
+#endif /* _P2PKP_DEBUG_H_ */
+
diff --git a/module/p2pkp_file.c b/module/p2pkp_file.c
new file mode 100644 (file)
index 0000000..48dc67c
--- /dev/null
@@ -0,0 +1,54 @@
+#include <asm/uaccess.h>
+#include <linux/fs.h>
+
+#include "p2pkp_file.h"
+#include "p2pkp_debug.h"
+
+struct file* p2pkp_open_file_read(const char *filename)
+{
+       struct file * file;
+       file = filp_open(filename, O_RDONLY, 0);
+       return IS_ERR_OR_NULL(file) ? NULL : file;
+}
+
+void p2pkp_close_file(struct file *file)
+{
+       filp_close(file,NULL);
+}
+
+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;
+       }
+       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);
+
+       offset = 0;
+       do {
+               read_bytes = file->f_op->read(file, buffer + offset, len, &file->f_pos);
+               if (read_bytes > 0) {
+                       offset += read_bytes;
+                       len -= read_bytes;
+               }
+       } while (/*(read_bytes < 0 && errno == EINVAL)||*/(read_bytes > 0 && len > 0));
+
+       set_fs(fs);
+
+       if (read_bytes < 0) {
+               ERROR("error while reading from file!");
+       }
+
+       return offset;
+}
+
diff --git a/module/p2pkp_file.h b/module/p2pkp_file.h
new file mode 100644 (file)
index 0000000..f98e32f
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _P2PKP_FILE_H_
+#define _P2PKP_FILE_H_
+
+
+struct file* p2pkp_open_file_read(const char *filename);
+void p2pkp_close_file(struct file *file);
+int p2pkp_read_from_file(struct file *file, char *buffer, int len);
+
+#endif /* _P2PKP_FILE_H_ */
diff --git a/module/p2pkp_net.c b/module/p2pkp_net.c
new file mode 100644 (file)
index 0000000..c178a71
--- /dev/null
@@ -0,0 +1,45 @@
+#include "p2pkp_net.h"
+#include "p2pkp_debug.h"
+
+#include <linux/in.h>
+#include <linux/errno.h>
+
+
+/* send datagram */
+int p2pkp_msgsend(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_sendmsg(s, &msg, (struct kvec *) msg.msg_iov, 1, len);
+}
+
+
+int p2pkp_create_udp_sock(struct socket **sock)
+{
+       if (!sock) {
+               ERROR("socket memory not specified");
+               return -EINVAL;
+       }
+
+       /* create UDP socket */
+       return sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, sock);
+}
+
+void p2pkp_destroy_udp_sock(struct socket *sock)
+{
+       sock_release(sock);
+}
diff --git a/module/p2pkp_net.h b/module/p2pkp_net.h
new file mode 100644 (file)
index 0000000..dd43124
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _P2PKP_NET_H_
+#define _P2PKP_NET_H_
+
+#include <net/sock.h>
+#include <linux/net.h>
+
+
+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);
+
+#endif /* _P2PKP_NET_H_ */
diff --git a/module/p2pkp_sock.c b/module/p2pkp_sock.c
new file mode 100644 (file)
index 0000000..d72fdb3
--- /dev/null
@@ -0,0 +1,322 @@
+#include <linux/net.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+
+#include "p2pkp.h"
+#include "p2pkp_net.h"
+#include "p2pkp_sock.h"
+#include "p2pkp_debug.h"
+#include "p2pkp_file.h"
+
+
+static int p2pkp_release(struct socket *sock);
+static int p2pkp_bind(struct socket *sock, struct sockaddr *myaddr,
+               int sockaddr_len);
+static int p2pkp_connect(struct socket *sock, struct sockaddr *vaddr,
+               int sockaddr_len, int flags);
+static int p2pkp_sendmsg(struct kiocb *iocb, struct socket *sock,
+               struct msghdr *m, size_t total_len);
+static int p2pkp_recvmsg(struct kiocb *iocb, struct socket *sock,
+               struct msghdr *m, size_t total_len, int flags);
+
+/* creates a socket */
+static int p2pkp_create(struct net *net, struct socket *sock, int protocol,
+               int kern);
+
+/* protocol */
+static struct proto p2pkp_proto = {
+       .name           = P2PKP_PROTO_NAME,
+       .owner          = THIS_MODULE,
+       .obj_size       = sizeof(struct p2pkp_sock),
+};
+
+/* protocol operations */
+static const struct proto_ops p2pkp_ops = {
+       .family         = PF_P2PKP,
+       .owner          = THIS_MODULE,
+       .release        = p2pkp_release,
+       .bind           = p2pkp_bind,
+       .connect        = p2pkp_connect,
+       .sendmsg        = p2pkp_sendmsg,
+       .recvmsg        = p2pkp_recvmsg,
+
+       /* unimplemented */
+       .poll           = datagram_poll,
+       .socketpair     = sock_no_socketpair,
+       .accept         = sock_no_accept,
+       .getname        = sock_no_getname,
+       .ioctl          = sock_no_ioctl,
+       .listen         = sock_no_listen,
+       .shutdown       = sock_no_shutdown,
+       .setsockopt     = sock_no_setsockopt,
+       .getsockopt     = sock_no_getsockopt,
+       .mmap           = sock_no_mmap,
+       .sendpage       = sock_no_sendpage,
+};
+
+
+/* family socket */
+static const struct net_proto_family p2pkp_family_ops = {
+       .family         = PF_P2PKP,
+       .create         = p2pkp_create,
+       .owner          = THIS_MODULE,
+};
+
+
+
+int p2pkp_register_protocol(void)
+{
+       int err;
+
+       err = sock_register(&p2pkp_family_ops);
+       if (err) {
+               ERROR("cannot register operations");
+               goto exit;
+       }
+
+       err = proto_register(&p2pkp_proto, 0);
+       if (err) {
+               ERROR("cannot register proto");
+               goto sock_unreg;
+       }
+       DEBUG("Successfully registered socket operations");
+
+       return 0;
+
+sock_unreg:
+       sock_unregister(PF_P2PKP);
+exit:
+       return err;
+
+}
+
+void p2pkp_unregister_protocol(void)
+{
+       DEBUG("Unregistering protocol");
+       proto_unregister(&p2pkp_proto);
+       sock_unregister(PF_P2PKP);
+       DEBUG("Successfully UNregistered socket operations");
+}
+
+
+static int p2pkp_release(struct socket *sock)
+{
+       struct sock *sk = sock->sk;
+       struct p2pkp_sock *ps = sock2p2pkp(sk);
+
+       if (!sk)
+               return 0;
+
+       lock_sock(sk);
+       sock_orphan(sk);
+       sk->sk_shutdown = SEND_SHUTDOWN;
+
+       skb_queue_purge(&sk->sk_receive_queue);
+       skb_queue_purge(&sk->sk_write_queue);
+       skb_queue_purge(&sk->sk_error_queue);
+
+       /* TODO: some statistics, don't know if really
+        * needed */
+       //sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
+
+       /* TODO do whatever is needed with ps */
+
+       if (!sock_flag(sk, SOCK_DEAD))
+               sk->sk_state_change(sk);
+
+       release_sock(sk);
+
+       sock_set_flag(sk, SOCK_DEAD);
+       sock->sk = NULL;
+
+       p2pkp_destroy_udp_sock(ps->net_sock);
+       
+       sock_put(sk);
+       DEBUG("Released the socket");
+       return 0;
+}
+
+static int p2pkp_bind(struct socket *sock, struct sockaddr *myaddr,
+               int sockaddr_len){return 0;}
+
+
+static int p2pkp_connect(struct socket *sock, struct sockaddr *vaddr,
+               int sockaddr_len, int flags)
+{
+       struct sock *sk = sock->sk;
+       struct p2pkp_sock *ps = sock2p2pkp(sk);
+       struct p2pkp_conn_info *pconn;
+
+       if (!sk || !vaddr || sockaddr_len != sizeof(struct sockaddr_in) ||
+                       vaddr->sa_family != AF_INET) {
+               ERROR("invalid socket parameters");
+               return -EINVAL;
+       }
+
+       pconn = kmalloc(sizeof(struct p2pkp_conn_info), GFP_KERNEL);
+       if (!pconn) {
+               ERROR("no more memory for new list element");
+               return -ENOMEM;
+       }
+
+       INIT_LIST_HEAD(&pconn->list);
+       memcpy(&pconn->sin, vaddr, sockaddr_len);
+
+       lock_sock(sk);
+
+       /* TODO spinlock required? */
+       list_add(&pconn->list, &ps->conn_list);
+
+       sock->state = SS_CONNECTED;
+       release_sock(sk);
+
+       DEBUG("Connected socket to a peer");
+
+       return 0;
+}
+
+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;
+       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;
+       struct list_head *pos;
+       struct p2pkp_conn_info *conn;
+
+       if (!sk || !sock ||
+                       (sin && sizeof(struct sockaddr_in) != m->msg_namelen)) {
+               ERROR("invalid socket parameters");
+               return -EINVAL;
+       }
+
+       if (sin && ((err = p2pkp_connect(sock, (struct sockaddr *)sin,
+                                               sizeof(struct sockaddr_in), 0)) < 0)) {
+               ERROR("cannot connect to socket");
+               return err;
+       }
+
+       lock_sock(sk);
+       if (!(sock->state & SS_CONNECTED)) {
+               ERROR("unconnected socket");
+               err = -ECONNREFUSED;
+               goto release;
+       }
+       release_sock(sk);
+
+       /* check if the file exists */
+       for (f_index = 0; f_index < m->msg_iovlen; f_index++) {
+               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);
+                       continue;
+               }
+               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");
+                               goto out_close;
+                       }
+                       if (bytes_read == 0)
+                               goto out_close;
+
+                       lock_sock(sk);
+                       /* iterate through all the connections to send the data */
+                       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);
+                               if (err < 0) {
+                                       ERROR("can't send first message");
+                                       goto out_conn;
+                               }
+                       }
+out_conn:
+                       release_sock(sk);
+               }
+
+out_close:
+
+               p2pkp_close_file(file);
+       }
+
+
+       DEBUG("Sending completed successfully");
+       err = 0;
+release:
+       release_sock(sk);
+       return err;
+}
+
+
+static int p2pkp_recvmsg(struct kiocb *iocb, struct socket *sock,
+               struct msghdr *m, size_t total_len, int flags){return 0;}
+
+
+static int p2pkp_create(struct net *net, struct socket *sock, int protocol,
+               int kern)
+{
+       struct sock *sk = NULL;
+       struct p2pkp_sock *ps;
+       int err = -ESOCKTNOSUPPORT;
+
+       DEBUG("Creating new P2PKP socket");
+       if (sock->type != SOCK_DGRAM) {
+               ERROR("P2PKP supports only SOCK_DGRAM sockets");
+               goto error;
+       }
+       if (protocol) {
+               ERROR("protocol %x not suported - currently only 0 is supported",
+                               protocol);
+               goto error;
+       }
+
+       sock->state = SS_UNCONNECTED;
+
+       err = -ENOBUFS;
+       sk = sk_alloc(net, PF_P2PKP, GFP_KERNEL, &p2pkp_proto);
+       if (unlikely(!sk)) {
+               ERROR("unable to create new socket");
+               goto error;
+       }
+
+       sock->ops = &p2pkp_ops;
+       sock_init_data(sock, sk);
+
+       sk->sk_reuse = 1;
+       sk->sk_no_check = 1;
+       sk->sk_family = PF_P2PKP;
+       sk->sk_protocol = protocol;
+       sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;
+
+       /* TODO init further data */
+       ps = sock2p2pkp(sk);
+
+       err = p2pkp_create_udp_sock(&ps->net_sock);
+       if (err < 0) {
+               ERROR("cannot create UDP socket");
+               goto error;
+       }
+       ps->buffer_len = P2PKP_DEFAULT_BUF_LEN;
+
+       INIT_LIST_HEAD(&ps->conn_list);
+       spin_lock_init(&ps->conn_lock);
+
+       DEBUG("Created new P2PKP socket");
+
+       return 0;
+error:
+       if (sk)
+               sock_put(sk);
+       return err;
+}
+
+
diff --git a/module/p2pkp_sock.h b/module/p2pkp_sock.h
new file mode 100644 (file)
index 0000000..96d25aa
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef _P2PKP_SOCKET_H_
+#define _P2PKP_SOCKET_H_
+
+#include <net/sock.h>
+
+#define P2PKP_DEFAULT_BUF_LEN  256
+
+struct p2pkp_conn_info {
+       struct sockaddr_in sin;
+       struct list_head list;
+};
+
+struct p2pkp_sock {
+       struct sock sk;
+       spinlock_t conn_lock;
+       struct list_head conn_list;
+       struct socket *net_sock;
+       unsigned int buffer_len;
+       unsigned char buffer[P2PKP_DEFAULT_BUF_LEN];
+       int bind_ifindex;       /* bound interface index; 0 for any interface */
+       __be16 bind_port;       /* bound port; 0 for unbound socks*/
+       __be16 rem_port;        /* remote port; 0 for unconnected socks */
+};
+
+/* P2PKP protocol name; used as identifier in /proc/net/protocols */
+#define P2PKP_PROTO_NAME       "P2PKP"
+
+
+/* converts a sock to a p2pkp_sock */
+#define sock2p2pkp(sock) ((struct p2pkp_sock *)(sock))
+/* converts a p2pkp_sock to a sock */
+#define p2pkp2sock(ps) ((struct sock *)(ps))
+
+/* converts a sockaddr to a sockaddr_p2pkp */
+#define sockaddr2p2pkp(sa) ((struct sockaddr_p2pkp *)(sa))
+/* converts a socaddr_p2pkp to a sockaddr */
+#define p2pkp2sockaddr(ps) ((struct sockaddr *)(ps))
+
+int p2pkp_register_protocol(void);
+void p2pkp_unregister_protocol(void);
+
+#endif /* _P2PKP_SOCKET_H_ */
diff --git a/module/p2psp.c b/module/p2psp.c
deleted file mode 100644 (file)
index a29d930..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Simple UDP implementation
- *
- * Răzvan Crainea
- * Tudor Cazangiu
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/net.h>
-#include <linux/in.h>
-
-MODULE_DESCRIPTION("P2P Swift Protocol");
-MODULE_AUTHOR("Razvan Crainea and Tudor Cazangiu");
-MODULE_LICENSE("GPL");
-
-#define LOG_LEVEL              KERN_ALERT
-#define P2PSP_LOCAL_PORT       60000
-#define P2PSP_REMOTE_PORT1     60001
-#define P2PSP_REMOTE_PORT2     60002
-#define MY_TEST_MESSAGE                "kernelsocket\n"
-
-#define ON                     1
-#define OFF                    0
-#define DEBUG                  ON
-
-#if DEBUG == ON
-#define LOG(s)                                 \
-       do {                                    \
-               printk(KERN_DEBUG s "\n");      \
-       } while (0)
-#else
-#define LOG(s)                                 \
-       do {} while (0)
-#endif
-
-#define print_sock_address(addr)               \
-       do {                                    \
-               printk(LOG_LEVEL "connection established to "   \
-                               NIPQUAD_FMT ":%d\n",            \
-                               NIPQUAD(addr.sin_addr.s_addr),  \
-                               ntohs(addr.sin_port));          \
-       } while (0)
-
-static struct socket *sock;    /* UDP server */
-
-/* send datagram */
-static int p2psp_msgsend(struct socket *s, short port)
-{
-       /* address to send to */
-       struct sockaddr_in raddr = {
-               .sin_family     = AF_INET,
-               .sin_port       = htons(port),
-               .sin_addr       = { htonl(INADDR_LOOPBACK) }
-       };
-       int raddrlen = sizeof(raddr);
-       /* message */
-       struct msghdr msg;
-       struct iovec iov;
-       char *buffer = MY_TEST_MESSAGE;
-       int len = strlen(buffer) + 1;
-
-       /* build message */
-       iov.iov_base = buffer;
-       iov.iov_len = len;
-       msg.msg_name = &raddr;
-       msg.msg_namelen = raddrlen;
-       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_sendmsg(s, &msg, (struct kvec *) msg.msg_iov, 1, len);
-}
-
-int __init p2psp_sock_init(void)
-{
-       int err;
-       /* address to bind on */
-       struct sockaddr_in addr = {
-               .sin_family     = AF_INET,
-               .sin_port       = htons(P2PSP_LOCAL_PORT),
-               .sin_addr       = { htonl(INADDR_LOOPBACK) }
-       };
-       int addrlen = sizeof(addr);
-
-       /* create UDP socket */
-       err = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
-       if (err < 0) {
-               printk(LOG_LEVEL "can't create socket\n");
-               goto out;
-       }
-
-       /* bind socket to loopback on port P2PSP_LOCAL_PORT */
-       err = sock->ops->bind(sock, (struct sockaddr *) &addr, addrlen);
-       if (err < 0) {
-               printk(LOG_LEVEL "can't bind socket\n");
-               goto out_release;
-       }
-
-       /* send first message */
-       err = p2psp_msgsend(sock, P2PSP_REMOTE_PORT1);
-       if (err < 0) {
-               printk(LOG_LEVEL "can't send first message\n");
-               goto out_release;
-       }
-
-       /* send second message */
-       err = p2psp_msgsend(sock, P2PSP_REMOTE_PORT2);
-       if (err < 0) {
-               printk(LOG_LEVEL "can't send second message\n");
-               goto out_release;
-       }
-
-
-       return 0;
-
-out_release:
-       /* cleanup socket */
-       sock_release(sock);
-out:
-       return err;
-}
-
-void __exit p2psp_sock_exit(void)
-{
-       /* cleanup socket */
-       sock_release(sock);
-}
-
-module_init(p2psp_sock_init);
-module_exit(p2psp_sock_exit);
diff --git a/module/test.sh b/module/test.sh
deleted file mode 100755 (executable)
index a26b09e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/bash
-
-LISTENERS=2
-START_PORT=60001
-
-#use nc.traditional
-echo 2 | update-alternatives --config nc &> /dev/null
-
-#set -x
-
-# listen for UDP packets on localhost, port 60001 (run in background)
-for listener in $(seq $LISTENERS); do
-       netcat -l -u -p $START_PORT &
-       pids="$pids $!"
-       START_PORT=$(($START_PORT + 1))
-done
-
-# wait for netcat to start listening
-sleep 1
-
-# insert module, causing the message to be sent
-insmod p2psp.ko
-
-# remove module
-rmmod p2psp
-
-# kill netcat
-for pid in $pids; do
-       kill $pid &> /dev/null
-done
diff --git a/test/client/Makefile b/test/client/Makefile
new file mode 100644 (file)
index 0000000..8d5c7ad
--- /dev/null
@@ -0,0 +1,7 @@
+FILE=client
+
+$(FILE):$(FILE).o
+
+.PHONY: clean
+clean:
+       -rm -rf $(FILE) $(FILE).o
diff --git a/test/client/client b/test/client/client
new file mode 100755 (executable)
index 0000000..6f7edef
Binary files /dev/null and b/test/client/client differ
diff --git a/test/client/client.c b/test/client/client.c
new file mode 100644 (file)
index 0000000..1e70583
--- /dev/null
@@ -0,0 +1,69 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <errno.h>
+#include <netdb.h>
+
+#include "p2pkp.h"
+
+#define TEST_FILE "/root/Dropbox/school/p2pkp/test/client/test_file"
+
+int main(int argc, char **argv)
+{
+       int sock, err;
+       struct sockaddr_in psin;
+       struct hostent *host;
+
+       if (argc % 2 == 0 || argc < 2) {
+               fprintf(stderr, "Usage: %s <peer_ip1> <peer_port1> "
+                               "<pper_ip2> <peer_port2> ...\n", argv[0]);
+               return -1;
+       }
+
+       printf("Opening AF_P2PKP socket\n");
+
+       sock = socket(AF_P2PKP, SOCK_DGRAM, 0);
+       printf("Socket returned: %d\n", sock);
+
+       if (sock < 0) {
+               printf("Cannot create AF_P2PKP socket: %s(%d)\n",
+                               strerror(errno), errno);
+               return -1;
+       }
+       printf("Successfully created AF_P2PKP socket: %d\n", sock);
+
+       argv++;
+       while (*argv) {
+               printf("Connecting to: %s:%s\n", argv[0], argv[1]);
+
+               host = gethostbyname(argv[0]);
+               psin.sin_family = AF_INET;
+               psin.sin_port = htons(atoi(argv[1]));
+               psin.sin_addr = *((struct in_addr *)host->h_addr);
+
+               if (connect(sock, (struct sockaddr *)&psin,
+                                       sizeof(struct sockaddr_in)) == -1) 
+               {
+                       printf("Cannot connect to server: %s(%d)\n", strerror(errno), errno);
+                       return -1;
+               }
+               printf("Connected to: %s:%s\n", argv[0], argv[1]);
+               argv+=2;
+       }
+
+       printf("Starting to write on the socket\n");
+
+       err = write(sock, TEST_FILE, sizeof(TEST_FILE) - 1);
+       if (err < 0) {
+               printf("Error while sending file %s: %s(%d)\n", TEST_FILE,
+                               strerror(errno), errno);
+               return err;
+       }
+
+       printf("Successfully written file\n");
+
+       return 0;
+}
diff --git a/test/client/p2pkp.h b/test/client/p2pkp.h
new file mode 100644 (file)
index 0000000..f18d258
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _P2PKP_H_
+#define _P2PKP_H_
+
+#define AF_P2PKP               19
+#define PF_P2PKP               AF_P2PKP
+
+#endif /* _P2PKP_H_ */
diff --git a/test/client/test.sh b/test/client/test.sh
new file mode 100755 (executable)
index 0000000..b961f72
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+MODULE_NAME=af_p2pkp
+MODULE_DIR=../../module
+CLIENT=./client
+
+LISTENERS_PORTS=(
+       60000
+       60001
+       60002
+)
+
+
+#use nc.traditional
+echo 2 | update-alternatives --config nc &> /dev/null
+
+#increase tests debugging
+set -x
+
+# listen for UDP packets on localhost, port 60000 (run in background)
+for listener in "${LISTENERS_PORTS[@]}"; do
+       netcat -l -u -p $listener &
+       pids="$pids $!"
+       ARGUMENTS="127.0.0.1 $listener $ARGUMENTS"
+done
+
+# wait for netcat to start listening
+sleep 1
+
+# insert module, causing the message to be sent
+insmod $MODULE_DIR/$MODULE_NAME.ko
+
+$CLIENT $ARGUMENTS
+
+# remove module
+rmmod $MODULE_NAME
+
+# kill netcat
+for pid in $pids; do
+       kill $pid &> /dev/null
+done
diff --git a/test/client/test_file b/test/client/test_file
new file mode 100644 (file)
index 0000000..fc5ca98
--- /dev/null
@@ -0,0 +1,2 @@
+TEST 1
+TEST 2