diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2012-02-26 23:13:08 +0100 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2012-02-26 23:13:08 +0100 |
commit | 13306fc146b4839d511287f29df8572a80bf8914 (patch) | |
tree | 081330075fabb3a93b0c9c49b9f9f2317934381e | |
parent | 57a63fc9304e71ddd2cf434cc4c8789a1a3a3c88 (diff) | |
download | fastd-13306fc146b4839d511287f29df8572a80bf8914.tar fastd-13306fc146b4839d511287f29df8572a80bf8914.zip |
Implement I/O for a fixed peer
-rw-r--r-- | src/Makefile | 13 | ||||
-rw-r--r-- | src/fastd.c | 219 | ||||
-rw-r--r-- | src/fastd.h | 64 | ||||
-rw-r--r-- | src/handshake.c | 95 | ||||
-rw-r--r-- | src/handshake.h | 36 | ||||
-rw-r--r-- | src/method_null.c | 18 | ||||
-rw-r--r-- | src/packet.h | 7 | ||||
-rw-r--r-- | src/queue.h | 74 | ||||
-rw-r--r-- | src/task.c | 63 | ||||
-rw-r--r-- | src/task.h | 69 |
10 files changed, 582 insertions, 76 deletions
diff --git a/src/Makefile b/src/Makefile index 90619ec..caa6f9f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,10 +1,11 @@ all : fastd -fastd : fastd.o method_null.o - gcc -Wall -o $@ $^ +fastd : fastd.o method_null.o task.o handshake.o -fastd.o : fastd.c fastd.h packet.h - gcc -Wall -c -o $@ $< +fastd.o : fastd.c fastd.h task.h queue.h handshake.h +handshake.o : handshake.c packet.h handshake.h +method_null.o : method_null.c fastd.h task.h +task.o : task.c task.h queue.h -method_null.o : method_null.c fastd.h - gcc -Wall -c -o $@ $< +clean : + rm -f fastd fastd.o method_null.o task.o diff --git a/src/fastd.c b/src/fastd.c index 42478b2..b0cf3b4 100644 --- a/src/fastd.c +++ b/src/fastd.c @@ -25,8 +25,12 @@ */ +#include "fastd.h" +#include "handshake.h" +#include "task.h" + +#include <arpa/inet.h> #include <fcntl.h> -#include <linux/if_ether.h> #include <linux/if_tun.h> #include <net/if.h> #include <poll.h> @@ -36,120 +40,227 @@ #include <sys/socket.h> #include <unistd.h> -#include "fastd.h" -#include "packet.h" - extern fastd_method fastd_method_null; -static int init_tuntap(const fastd_context *ctx) { - int tunfd; +static void init_tuntap(fastd_context *ctx) { struct ifreq ifr; pr_debug(ctx, "Initializing tun/tap device..."); - if ((tunfd = open("/dev/net/tun", O_RDWR)) < 0) - exit_fatal_errno(ctx, "Could not open tun/tap device file"); + if ((ctx->tunfd = open("/dev/net/tun", O_RDWR)) < 0) + exit_errno(ctx, "Could not open tun/tap device file"); memset(&ifr, 0, sizeof(ifr)); - // strcpy(ifr.ifr_name, name); + + if (ctx->conf->ifname) + strncpy(ifr.ifr_name, ctx->conf->ifname, IF_NAMESIZE-1); + ifr.ifr_flags = IFF_TAP; ifr.ifr_flags |= IFF_NO_PI; - if (ioctl(tunfd, TUNSETIFF, (void *)&ifr) < 0) - exit_fatal_errno(ctx, "TUNSETIFF ioctl failed"); + if (ioctl(ctx->tunfd, TUNSETIFF, (void *)&ifr) < 0) + exit_errno(ctx, "TUNSETIFF ioctl failed"); - return tunfd; + pr_debug(ctx, "Tun/tap device initialized."); +} + +static void init_socket(fastd_context *ctx) { + pr_debug(ctx, "Initializing UDP socket..."); + + if ((ctx->sockfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) + exit_errno(ctx, "socket"); + + struct sockaddr_in bindaddr; + bindaddr.sin_family = AF_INET; + bindaddr.sin_addr.s_addr = ctx->conf->bind_address; + bindaddr.sin_port = ctx->conf->bind_port; + + if (bind(ctx->sockfd, (struct sockaddr*)&bindaddr, sizeof(struct sockaddr_in))) + exit_errno(ctx, "bind"); + + pr_debug(ctx, "UDP socket initialized."); } static void configure(fastd_context *ctx, fastd_config *conf) { conf->loglevel = LOG_DEBUG; + conf->ifname = NULL; + conf->bind_address = htonl(INADDR_ANY); + conf->bind_port = htons(1337); conf->mtu = 1500; conf->protocol = PROTOCOL_ETHERNET; conf->method = &fastd_method_null; - conf->n_peers = 0; - conf->peers = NULL; -} -static size_t get_max_packet_size(const fastd_context *ctx) { - switch (ctx->conf->protocol) { - case PROTOCOL_ETHERNET: - return ctx->conf->mtu+ETH_HLEN; - case PROTOCOL_IP: - return ctx->conf->mtu; - default: - exit_fatal_bug(ctx, "invalid protocol"); + conf->peers = malloc(sizeof(fastd_peer_config)); + conf->peers->next = NULL; + conf->peers->address = inet_addr("172.22.184.1"); + conf->peers->port = htons(1337); + + ctx->peers = NULL; + fastd_peer **current_peer = &ctx->peers; + + for (fastd_peer_config *peer_conf = conf->peers; peer_conf; peer_conf = peer_conf->next) { + *current_peer = malloc(sizeof(fastd_peer)); + (*current_peer)->next = NULL; + (*current_peer)->config = peer_conf; + (*current_peer)->address = peer_conf->address; + (*current_peer)->port = peer_conf->port; + (*current_peer)->state = STATE_WAIT; + (*current_peer)->last_req_id = 0; + (*current_peer)->addresses = NULL; + + current_peer = &(*current_peer)->next; } } -static void *get_source_address(const fastd_context *ctx, void *buffer) { +static void* get_source_address(const fastd_context *ctx, void *buffer) { switch (ctx->conf->protocol) { case PROTOCOL_ETHERNET: return &((struct ethhdr*)buffer)->h_source; case PROTOCOL_IP: return NULL; default: - exit_fatal_bug(ctx, "invalid protocol"); + exit_bug(ctx, "invalid protocol"); } } -static void *get_dest_address(const fastd_context *ctx, void *buffer) { +static void* get_dest_address(const fastd_context *ctx, void *buffer) { switch (ctx->conf->protocol) { case PROTOCOL_ETHERNET: return &((struct ethhdr*)buffer)->h_dest; case PROTOCOL_IP: return NULL; default: - exit_fatal_bug(ctx, "invalid protocol"); + exit_bug(ctx, "invalid protocol"); } } -static void run(const fastd_context *ctx) { - int tunfd; +static void handle_tasks(fastd_context *ctx) { + fastd_task *task; + while ((task = fastd_task_get(ctx)) != NULL) { + switch (task->type) { + case TASK_SEND: + if (task->send.peer) { + struct msghdr msg; + memset(&msg, 0, sizeof(msg)); + + struct sockaddr_in sendaddr; + sendaddr.sin_family = AF_INET; + sendaddr.sin_addr.s_addr = task->send.peer->address; + sendaddr.sin_port = task->send.peer->port; + + msg.msg_name = &sendaddr; + msg.msg_namelen = sizeof(sendaddr); + + struct iovec vec[2] = { { .iov_base = &task->send.packet_type, .iov_len = 1 }, task->send.buffer }; + + msg.msg_iov = vec; + msg.msg_iovlen = 2; + + sendmsg(ctx->sockfd, &msg, 0); + } + + free(task->send.buffer.iov_base); + break; + + case TASK_HANDLE_RECV: + // TODO Handle source address + writev(ctx->tunfd, &task->handle_recv.buffer, 1); + free(task->handle_recv.buffer.iov_base); + break; + + default: + exit_bug(ctx, "invalid task type"); + } - tunfd = init_tuntap(ctx); + free(task); + } +} - struct pollfd fds[ctx->conf->n_peers+1]; - fds[0].fd = tunfd; +static void handle_input(fastd_context *ctx) { + struct pollfd fds[2]; + fds[0].fd = ctx->tunfd; fds[0].events = POLLIN; + fds[1].fd = ctx->sockfd; + fds[1].events = POLLIN; - while (1) { - int ret = poll(fds, 1, -1); - if (ret < 0) - exit_fatal_errno(ctx, "poll error"); + int ret = poll(fds, 2, -1); + if (ret < 0) + exit_errno(ctx, "poll"); + + if (fds[0].revents & POLLIN) { + size_t max_len = fastd_max_packet_size(ctx); + void *buffer = malloc(max_len); - if (fds[0].revents & POLLIN) { - size_t max_len = get_max_packet_size(ctx); - char buffer[max_len]; + ssize_t len = read(ctx->tunfd, buffer, max_len); + if (len < 0) + exit_errno(ctx, "read"); - unsigned len = read(tunfd, buffer, max_len); - if (len < 0) - exit_fatal_errno(ctx, "read"); + uint8_t *src_addr = get_source_address(ctx, buffer); + uint8_t *dest_addr = get_dest_address(ctx, buffer); - uint8_t *src_addr = get_source_address(ctx, buffer); - uint8_t *dest_addr = get_dest_address(ctx, buffer); + pr_debug(ctx, "A packet with length %u is to be sent from %02x:%02x:%02x:%02x:%02x:%02x to %02x:%02x:%02x:%02x:%02x:%02x", + (unsigned)len, src_addr[0], src_addr[1], src_addr[2], src_addr[3], src_addr[4], src_addr[5], + dest_addr[0], dest_addr[1], dest_addr[2], dest_addr[3], dest_addr[4], dest_addr[5]); - pr_debug(ctx, "A packet with length %u was received from %02x:%02x:%02x:%02x:%02x:%02x to %02x:%02x:%02x:%02x:%02x:%02x", - len, src_addr[0], src_addr[1], src_addr[2], src_addr[3], src_addr[4], src_addr[5], - dest_addr[0], dest_addr[1], dest_addr[2], dest_addr[3], dest_addr[4], dest_addr[5]); + // TODO find correct peer - ctx->conf->method->method_send(ctx, buffer, len); + struct iovec vec = { .iov_base = buffer, .iov_len = len }; + ctx->conf->method->method_send(ctx, ctx->peers, vec); + } + if (fds[1].revents & POLLIN) { + size_t max_len = ctx->conf->method->method_max_packet_size(ctx); // 1 is the packet type header + void *buffer = malloc(max_len); + + uint8_t packet_type; + + struct iovec vec[2] = {{ .iov_base = &packet_type, .iov_len = 1 }, { .iov_base = buffer, .iov_len = max_len }}; + struct sockaddr_in recvaddr; + + struct msghdr msg; + memset(&msg, 0, sizeof(msg)); + + msg.msg_name = &recvaddr; + msg.msg_namelen = sizeof(recvaddr); + msg.msg_iov = vec; + msg.msg_iovlen = 2; + + ssize_t len = recvmsg(ctx->sockfd, &msg, 0); + if (len < 0) + pr_warn(ctx, "recvfrom: %s", strerror(errno)); + + // TODO get peer + + switch (packet_type) { + case 0: + vec[1].iov_len = len - 1; + ctx->conf->method->method_handle_recv(ctx, NULL, vec[1]); + break; + + default: + fastd_handshake_handle(ctx, NULL, packet_type, vec[1]); + free(buffer); + break; } } } -int main() -{ - fastd_context ctx = { - .conf = NULL, - }; +int main() { + fastd_context ctx; + memset(&ctx, 0, sizeof(ctx)); fastd_config conf; configure(&ctx, &conf); ctx.conf = &conf; - run(&ctx); + init_tuntap(&ctx); + init_socket(&ctx); + + while (1) { + handle_tasks(&ctx); + handle_input(&ctx); + } return 0; } diff --git a/src/fastd.h b/src/fastd.h index 06b69b2..16be512 100644 --- a/src/fastd.h +++ b/src/fastd.h @@ -28,11 +28,16 @@ #ifndef _FASTD_FASTD_H_ #define _FASTD_FASTD_H_ +#include "queue.h" + #include <errno.h> +#include <linux/if_ether.h> +#include <netinet/in.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> +#include <sys/uio.h> typedef enum _fastd_loglevel { @@ -51,39 +56,68 @@ typedef enum _fastd_protocol { typedef struct _fastd_peer_config { struct _fastd_peer_config *next; + + in_addr_t address; + in_port_t port; } fastd_peer_config; +typedef enum _fastd_peer_state { + STATE_WAIT, + STATE_HANDSHAKE_SENT, + STATE_ESTABLISHED, +} fastd_peer_state; -typedef struct _fastd_peer_state { - struct _fastd_peer_state *next; +typedef struct _fastd_peer { + struct _fastd_peer *next; const fastd_peer_config *config; -} fastd_peer_state; + + in_addr_t address; + in_port_t port; + + fastd_peer_state state; + uint8_t last_req_id; + + void **addresses; +} fastd_peer; typedef struct _fastd_context fastd_context; typedef struct _fastd_method { const char *name; - void (*method_init)(const fastd_context *ctx); - void (*method_recv)(const fastd_context *ctx, void *buffer, size_t len); - void (*method_send)(const fastd_context *ctx, void *buffer, size_t len); + size_t (*method_max_packet_size)(fastd_context *ctx); + + void (*method_init)(fastd_context *ctx, const fastd_peer *peer); + + void (*method_handle_recv)(fastd_context *ctx, const fastd_peer *peer, struct iovec buffer); + void (*method_send)(fastd_context *ctx, const fastd_peer *peer, struct iovec buffer); } fastd_method; typedef struct _fastd_config { fastd_loglevel loglevel; + char *ifname; + + in_addr_t bind_address; + in_port_t bind_port; + uint16_t mtu; fastd_protocol protocol; fastd_method *method; - unsigned n_peers; fastd_peer_config *peers; } fastd_config; struct _fastd_context { const fastd_config *conf; + + fastd_peer *peers; + fastd_queue task_queue; + + int tunfd; + int sockfd; }; @@ -96,7 +130,19 @@ struct _fastd_context { #define pr_debug(context, args...) pr_log(context, LOG_DEBUG, args) #define exit_fatal(context, args...) do { pr_fatal(context, args); exit(1); } while(0) -#define exit_fatal_bug(context, message) exit_fatal(context, "BUG: %s", message) -#define exit_fatal_errno(context, message) exit_fatal(context, "%s: %s", message, strerror(errno)) +#define exit_bug(context, message) exit_fatal(context, "BUG: %s", message) +#define exit_errno(context, message) exit_fatal(context, "%s: %s", message, strerror(errno)) + + +static inline size_t fastd_max_packet_size(const fastd_context *ctx) { + switch (ctx->conf->protocol) { + case PROTOCOL_ETHERNET: + return ctx->conf->mtu+ETH_HLEN; + case PROTOCOL_IP: + return ctx->conf->mtu; + default: + exit_bug(ctx, "invalid protocol"); + } +} #endif /* _FASTD_FASTD_H_ */ diff --git a/src/handshake.c b/src/handshake.c new file mode 100644 index 0000000..f9a1734 --- /dev/null +++ b/src/handshake.c @@ -0,0 +1,95 @@ +/* + Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net> + Partly based on QuickTun Copyright (c) 2010, Ivo Smits <Ivo@UCIS.nl>. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "handshake.h" +#include "packet.h" +#include "task.h" + +#include <string.h> + + +void fastd_handshake_send(fastd_context *ctx, const fastd_peer *peer) { + size_t method_len = strlen(ctx->conf->method->name); + size_t len = sizeof(fastd_packet_request)+method_len; + fastd_packet_request *request = malloc(len); + + request->reply = 0; + request->cp = 0; + request->req_id = 0; + request->rsv = 0; + request->flags = 0; + request->proto = ctx->conf->protocol; + request->method_len = method_len; + strncpy(request->method_name, ctx->conf->method->name, method_len); + + struct iovec buffer = { .iov_base = request, .iov_len = len }; + fastd_task_put_send_handshake(ctx, peer, buffer); +} + +void fastd_handshake_handle(fastd_context *ctx, const fastd_peer *peer, uint8_t packet_type, struct iovec buffer) { + if (packet_type != 1) + return; // TODO + + if (buffer.iov_len < sizeof(fastd_packet_any)) + return; + + fastd_packet *packet = buffer.iov_base; + + if (!packet->any.reply && !packet->any.cp) { + if (buffer.iov_len < sizeof(fastd_packet_request)) + return; + + if (buffer.iov_len < sizeof(fastd_packet_request) + packet->request.method_len) + return; + + if (packet->request.flags) + return; // TODO + + if (packet->request.proto != ctx->conf->protocol) + return; // TODO + + if (packet->request.method_len != strlen(ctx->conf->method->name) || + strncmp(packet->request.method_name, ctx->conf->method->name, packet->request.method_len)) + return; // TODO + + + fastd_packet_reply *reply = malloc(sizeof(fastd_packet_reply)); + + reply->reply = 1; + reply->cp = 0; + reply->req_id = packet->request.req_id; + reply->rsv = 0; + reply->reply_code = REPLY_SUCCESS; + + free(packet); + + buffer.iov_base = reply; + buffer.iov_len = sizeof(fastd_packet_reply); + + fastd_task_put_send_handshake(ctx, peer, buffer); + } +} diff --git a/src/handshake.h b/src/handshake.h new file mode 100644 index 0000000..7fbc549 --- /dev/null +++ b/src/handshake.h @@ -0,0 +1,36 @@ +/* + Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net> + Partly based on QuickTun Copyright (c) 2010, Ivo Smits <Ivo@UCIS.nl>. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _FASTD_HANDSHAKE_H_ +#define _FASTD_HANDSHAKE_H_ + +#include "fastd.h" + +void fastd_handshake_send(fastd_context *ctx, const fastd_peer *peer); +void fastd_handshake_handle(fastd_context *ctx, const fastd_peer *peer, uint8_t packet_type, struct iovec buffer); + +#endif /* _FASTD_HANDSHAKE_H_ */ diff --git a/src/method_null.c b/src/method_null.c index fd41110..dea84d4 100644 --- a/src/method_null.c +++ b/src/method_null.c @@ -25,21 +25,31 @@ */ #include "fastd.h" +#include "task.h" -static void null_init(const fastd_context *ctx) { +static size_t null_max_packet_size(fastd_context *ctx) { + return fastd_max_packet_size(ctx); } -static void null_recv(const fastd_context *ctx, void *buffer, size_t len) { +static void null_init(fastd_context *ctx, const fastd_peer *peer) { + struct iovec buffer = { .iov_base = NULL, .iov_len = 0 }; + fastd_task_put_send(ctx, peer, buffer); } -static void null_send(const fastd_context *ctx, void *buffer, size_t len) { +static void null_handle_recv(fastd_context *ctx, const fastd_peer *peer, struct iovec buffer) { + fastd_task_put_handle_recv(ctx, peer, buffer); +} + +static void null_send(fastd_context *ctx, const fastd_peer *peer, struct iovec buffer) { + fastd_task_put_send(ctx, peer, buffer); } const fastd_method fastd_method_null = { .name = "null", + .method_max_packet_size = null_max_packet_size, .method_init = null_init, - .method_recv = null_recv, + .method_handle_recv = null_handle_recv, .method_send = null_send, }; diff --git a/src/packet.h b/src/packet.h index 79b1984..548b9a4 100644 --- a/src/packet.h +++ b/src/packet.h @@ -29,8 +29,11 @@ #define _FASTD_PACKET_H_ +typedef enum _fastd_reply_code { + REPLY_SUCCESS = 0, +} fastd_reply_code; + typedef struct __attribute__ ((__packed__)) _fastd_packet_any { - unsigned type : 8; unsigned reply : 1; unsigned cp : 1; unsigned req_id : 6; @@ -38,7 +41,6 @@ typedef struct __attribute__ ((__packed__)) _fastd_packet_any { } fastd_packet_any; typedef struct __attribute__ ((__packed__)) _fastd_packet_request { - unsigned type : 8; unsigned reply : 1; unsigned cp : 1; unsigned req_id : 6; @@ -50,7 +52,6 @@ typedef struct __attribute__ ((__packed__)) _fastd_packet_request { } fastd_packet_request; typedef struct __attribute__ ((__packed__)) _fastd_packet_reply { - unsigned type : 8; unsigned reply : 1; unsigned cp : 1; unsigned req_id : 6; diff --git a/src/queue.h b/src/queue.h new file mode 100644 index 0000000..a196153 --- /dev/null +++ b/src/queue.h @@ -0,0 +1,74 @@ +/* + Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net> + Partly based on QuickTun Copyright (c) 2010, Ivo Smits <Ivo@UCIS.nl>. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _FASTD_QUEUE_H_ +#define _FASTD_QUEUE_H_ + +#include <stdlib.h> + + +typedef struct _fastd_queue_entry fastd_queue_entry; + +struct _fastd_queue_entry { + fastd_queue_entry *next; + void *data; +}; + +typedef struct _fastd_queue { + fastd_queue_entry *head; + fastd_queue_entry *tail; +} fastd_queue; + + +static inline void fastd_queue_put(fastd_queue *queue, void *data) { + fastd_queue_entry *entry = malloc(sizeof(fastd_queue_entry)); + entry->next = NULL; + entry->data = data; + + if (queue->tail) + queue->tail->next = entry; + else + queue->head = entry; + + queue->tail = entry; +} + +static inline void* fastd_queue_get(fastd_queue *queue) { + if (!queue->head) + return NULL; + + fastd_queue_entry *entry = queue->head; + queue->head = entry->next; + if (!queue->head) + queue->tail = NULL; + + void *data = entry->data; + free(entry); + return data; +} + +#endif /* _FASTD_QUEUE_H_ */ diff --git a/src/task.c b/src/task.c new file mode 100644 index 0000000..e2c4e99 --- /dev/null +++ b/src/task.c @@ -0,0 +1,63 @@ +/* + Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net> + Partly based on QuickTun Copyright (c) 2010, Ivo Smits <Ivo@UCIS.nl>. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "task.h" +#include "queue.h" + + +fastd_task* fastd_task_get(fastd_context *ctx) { + return fastd_queue_get(&ctx->task_queue); +} + +static void fastd_task_put_send_type(fastd_context *ctx, const fastd_peer *peer, uint8_t packet_type, struct iovec buffer) { + fastd_task_send *task = malloc(sizeof(fastd_task_send)); + + task->type = TASK_SEND; + task->peer = peer; + task->packet_type = packet_type; + task->buffer = buffer; + + fastd_queue_put(&ctx->task_queue, task); +} + +void fastd_task_put_send_handshake(fastd_context *ctx, const fastd_peer *peer, struct iovec buffer) { + fastd_task_put_send_type(ctx, peer, 1, buffer); +} + +void fastd_task_put_send(fastd_context *ctx, const fastd_peer *peer, struct iovec buffer) { + fastd_task_put_send_type(ctx, peer, 0, buffer); +} + +void fastd_task_put_handle_recv(fastd_context *ctx, const fastd_peer *peer, struct iovec buffer) { + fastd_task_handle_recv *task = malloc(sizeof(fastd_task_handle_recv)); + + task->type = TASK_HANDLE_RECV; + task->peer = peer; + task->buffer = buffer; + + fastd_queue_put(&ctx->task_queue, task); +} diff --git a/src/task.h b/src/task.h new file mode 100644 index 0000000..4c7bd65 --- /dev/null +++ b/src/task.h @@ -0,0 +1,69 @@ +/* + Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net> + Partly based on QuickTun Copyright (c) 2010, Ivo Smits <Ivo@UCIS.nl>. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _FASTD_TASK_H_ +#define _FASTD_TASK_H_ + +#include "fastd.h" + +#include <sys/uio.h> + + +typedef enum _fastd_task_type { + TASK_SEND, + TASK_HANDLE_RECV, +} fastd_task_type; + +typedef struct _fastd_task_send { + fastd_task_type type; + const fastd_peer *peer; + uint8_t packet_type; + struct iovec buffer; +} fastd_task_send; + +typedef struct _fastd_task_handle_recv { + fastd_task_type type; + const fastd_peer *peer; + uint8_t packet_type; + struct iovec buffer; +} fastd_task_handle_recv; + +typedef union _fastd_task { + fastd_task_type type; + fastd_task_send send; + fastd_task_handle_recv handle_recv; +} fastd_task; + + +fastd_task* fastd_task_get(fastd_context *ctx); + +void fastd_task_put_send_handshake(fastd_context *ctx, const fastd_peer *peer, struct iovec buffer); + +void fastd_task_put_send(fastd_context *ctx, const fastd_peer *peer, struct iovec buffer); +void fastd_task_put_handle_recv(fastd_context *ctx, const fastd_peer *peer, struct iovec buffer); + +#endif /* _FASTD_TASK_H_ */ |