]>
Commit | Line | Data |
---|---|---|
45a07212 MW |
1 | /** |
2 | * @file socket.c | |
79538669 | 3 | * |
df3c59d0 | 4 | * @brief Implementation of socket_t. |
79538669 | 5 | * |
45a07212 MW |
6 | */ |
7 | ||
8 | /* | |
9 | * Copyright (C) 2005 Jan Hutter, Martin Willi | |
10 | * Hochschule fuer Technik Rapperswil | |
11 | * | |
12 | * This program is free software; you can redistribute it and/or modify it | |
13 | * under the terms of the GNU General Public License as published by the | |
14 | * Free Software Foundation; either version 2 of the License, or (at your | |
15 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
16 | * | |
17 | * This program is distributed in the hope that it will be useful, but | |
18 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
19 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
20 | * for more details. | |
21 | */ | |
22 | ||
36c2c282 | 23 | #include <pthread.h> |
45a07212 MW |
24 | #include <sys/types.h> |
25 | #include <sys/socket.h> | |
26 | #include <string.h> | |
885608ff | 27 | #include <errno.h> |
45a07212 MW |
28 | #include <unistd.h> |
29 | #include <stdlib.h> | |
45a07212 | 30 | |
6c4b815f | 31 | #include "socket.h" |
45a07212 | 32 | |
021c2322 MW |
33 | #include <globals.h> |
34 | #include <utils/allocator.h> | |
35 | #include <utils/logger_manager.h> | |
88878242 | 36 | |
45a07212 | 37 | |
95c61cb9 JH |
38 | typedef struct private_socket_t private_socket_t; |
39 | ||
40 | /** | |
41 | * Private data of an socket_t object | |
42 | */ | |
43 | struct private_socket_t{ | |
45a07212 MW |
44 | /** |
45 | * public functions | |
46 | */ | |
47 | socket_t public; | |
79538669 | 48 | |
45a07212 MW |
49 | /** |
50 | * currently we only have one socket, maybe more in the future ? | |
51 | */ | |
885608ff | 52 | int socket_fd; |
df3c59d0 | 53 | |
885608ff MW |
54 | /** |
55 | * logger for this socket | |
56 | */ | |
57 | logger_t *logger; | |
6ada7959 | 58 | }; |
45a07212 | 59 | |
b9439120 MW |
60 | /** |
61 | * implementation of socket_t.receive | |
62 | */ | |
45a07212 MW |
63 | status_t receiver(private_socket_t *this, packet_t **packet) |
64 | { | |
45a07212 | 65 | char buffer[MAX_PACKET]; |
36c2c282 | 66 | int oldstate; |
a698ba19 | 67 | packet_t *pkt = packet_create(); |
79538669 | 68 | |
36c2c282 JH |
69 | /* add packet destroy handler for cancellation, enable cancellation */ |
70 | pthread_cleanup_push((void(*)(void*))pkt->destroy, (void*)pkt); | |
71 | pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); | |
a698ba19 MW |
72 | |
73 | pkt->source = host_create(AF_INET, "0.0.0.0", 0); | |
daa1c00e | 74 | pkt->destination = host_create(AF_INET, "0.0.0.0", 0); |
79538669 | 75 | |
885608ff MW |
76 | |
77 | this->logger->log(this->logger, CONTROL|MORE, "going to read from socket"); | |
45a07212 | 78 | /* do the read */ |
79538669 | 79 | pkt->data.len = recvfrom(this->socket_fd, buffer, MAX_PACKET, 0, |
a698ba19 MW |
80 | pkt->source->get_sockaddr(pkt->source), |
81 | pkt->source->get_sockaddr_len(pkt->source)); | |
79538669 | 82 | |
36c2c282 JH |
83 | /* reset cancellation, remove packet destroy handler (without executing) */ |
84 | pthread_setcancelstate(oldstate, NULL); | |
85 | pthread_cleanup_pop(0); | |
79538669 JH |
86 | |
87 | ||
88 | /* TODO: get senders destination address, using | |
b9439120 | 89 | * IP_PKTINFO and recvmsg */ |
79538669 | 90 | |
45a07212 MW |
91 | if (pkt->data.len < 0) |
92 | { | |
93 | pkt->destroy(pkt); | |
885608ff | 94 | this->logger->log(this->logger, ERROR, "error reading from socket: %s", strerror(errno)); |
45a07212 MW |
95 | return FAILED; |
96 | } | |
885608ff MW |
97 | |
98 | this->logger->log(this->logger, CONTROL, "received packet from %s:%d", | |
99 | pkt->source->get_address(pkt->source), | |
100 | pkt->source->get_port(pkt->source)); | |
79538669 | 101 | |
45a07212 | 102 | /* fill in packet */ |
6c4b815f | 103 | pkt->data.ptr = allocator_alloc(pkt->data.len); |
45a07212 | 104 | memcpy(pkt->data.ptr, buffer, pkt->data.len); |
79538669 | 105 | |
45a07212 MW |
106 | /* return packet */ |
107 | *packet = pkt; | |
79538669 JH |
108 | |
109 | return SUCCESS; | |
45a07212 | 110 | } |
79538669 | 111 | |
b9439120 MW |
112 | /** |
113 | * implementation of socket_t.send | |
114 | */ | |
79538669 | 115 | status_t sender(private_socket_t *this, packet_t *packet) |
45a07212 MW |
116 | { |
117 | ssize_t bytes_sent; | |
79538669 | 118 | |
885608ff MW |
119 | |
120 | this->logger->log(this->logger, CONTROL, "sending packet to %s:%d", | |
121 | packet->destination->get_address(packet->destination), | |
122 | packet->destination->get_port(packet->destination)); | |
45a07212 | 123 | /* send data */ |
79538669 | 124 | bytes_sent = sendto(this->socket_fd, packet->data.ptr, packet->data.len, |
a698ba19 MW |
125 | 0, packet->destination->get_sockaddr(packet->destination), |
126 | *(packet->destination->get_sockaddr_len(packet->destination))); | |
79538669 JH |
127 | |
128 | if (bytes_sent != packet->data.len) | |
45a07212 | 129 | { |
885608ff | 130 | this->logger->log(this->logger, ERROR, "error writing to socket: %s", strerror(errno)); |
45a07212 MW |
131 | return FAILED; |
132 | } | |
133 | return SUCCESS; | |
134 | } | |
79538669 | 135 | |
b9439120 MW |
136 | /** |
137 | * implementation of socket_t.destroy | |
138 | */ | |
df3c59d0 | 139 | void destroy(private_socket_t *this) |
45a07212 MW |
140 | { |
141 | close(this->socket_fd); | |
885608ff | 142 | global_logger_manager->destroy_logger(global_logger_manager, this->logger); |
79538669 | 143 | allocator_free(this); |
45a07212 MW |
144 | } |
145 | ||
9317c2a1 | 146 | socket_t *socket_create(u_int16_t port) |
45a07212 | 147 | { |
6c4b815f | 148 | private_socket_t *this = allocator_alloc_thing(private_socket_t); |
45a07212 | 149 | struct sockaddr_in addr; |
79538669 | 150 | |
45a07212 MW |
151 | /* public functions */ |
152 | this->public.send = (status_t(*)(socket_t*, packet_t*))sender; | |
153 | this->public.receive = (status_t(*)(socket_t*, packet_t**))receiver; | |
df3c59d0 | 154 | this->public.destroy = (void(*)(socket_t*))destroy; |
885608ff MW |
155 | |
156 | this->logger = global_logger_manager->create_logger(global_logger_manager, SOCKET, NULL); | |
79538669 | 157 | |
45a07212 MW |
158 | /* create default ipv4 socket */ |
159 | this->socket_fd = socket(PF_INET, SOCK_DGRAM, 0); | |
885608ff MW |
160 | if (this->socket_fd < 0) |
161 | { | |
162 | this->logger->log(this->logger, ERROR, "unable to open socket: %s", strerror(errno)); | |
163 | global_logger_manager->destroy_logger(global_logger_manager, this->logger); | |
79538669 | 164 | allocator_free(this); |
45a07212 | 165 | return NULL; |
79538669 JH |
166 | } |
167 | ||
b9439120 | 168 | /* bind socket to all interfaces */ |
45a07212 MW |
169 | addr.sin_family = AF_INET; |
170 | addr.sin_addr.s_addr = INADDR_ANY; | |
9317c2a1 | 171 | addr.sin_port = htons(port); |
885608ff MW |
172 | if (bind(this->socket_fd,(struct sockaddr*)&addr, sizeof(addr)) < 0) |
173 | { | |
174 | this->logger->log(this->logger, ERROR, "unable to bind socket to port %d: %s", port, strerror(errno)); | |
175 | global_logger_manager->destroy_logger(global_logger_manager, this->logger); | |
79538669 | 176 | allocator_free(this); |
45a07212 MW |
177 | return NULL; |
178 | } | |
79538669 | 179 | |
45a07212 MW |
180 | return (socket_t*)this; |
181 | } |