blob: 8a1a75edf1797ab539b59b5ade37781a63b18b1d [file] [log] [blame]
Sharvil Nanavatic2031c42014-07-25 15:50:17 -07001/******************************************************************************
2 *
3 * Copyright (C) 2014 Google, Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19#define LOG_TAG "bt_osi_socket"
20
Sharvil Nanavati98bf85f2014-08-27 19:05:40 -070021#include <asm/ioctls.h>
Sharvil Nanavatic2031c42014-07-25 15:50:17 -070022#include <assert.h>
23#include <errno.h>
24#include <netinet/in.h>
25#include <string.h>
Sharvil Nanavati98bf85f2014-08-27 19:05:40 -070026#include <sys/ioctl.h>
Sharvil Nanavatic2031c42014-07-25 15:50:17 -070027#include <sys/socket.h>
28#include <sys/types.h>
29#include <unistd.h>
Sharvil Nanavatic2031c42014-07-25 15:50:17 -070030
Zach Johnson384f8a92014-08-25 23:22:24 -070031#include "allocator.h"
Sharvil Nanavatifbf89082014-08-13 00:40:49 -070032#include "osi.h"
Sharvil Nanavati44802762014-12-23 23:08:58 -080033#include "osi/include/log.h"
Sharvil Nanavatic2031c42014-07-25 15:50:17 -070034#include "reactor.h"
35#include "socket.h"
36
37struct socket_t {
Sharvil Nanavatifbf89082014-08-13 00:40:49 -070038 int fd;
39 reactor_object_t *reactor_object;
Sharvil Nanavatic2031c42014-07-25 15:50:17 -070040 socket_cb read_ready;
41 socket_cb write_ready;
Sharvil Nanavatifbf89082014-08-13 00:40:49 -070042 void *context; // Not owned, do not free.
Sharvil Nanavatic2031c42014-07-25 15:50:17 -070043};
44
45static void internal_read_ready(void *context);
46static void internal_write_ready(void *context);
47
48socket_t *socket_new(void) {
Zach Johnson384f8a92014-08-25 23:22:24 -070049 socket_t *ret = (socket_t *)osi_calloc(sizeof(socket_t));
Sharvil Nanavatic2031c42014-07-25 15:50:17 -070050 if (!ret) {
Sharvil Nanavati44802762014-12-23 23:08:58 -080051 LOG_ERROR("%s unable to allocate memory for socket.", __func__);
Sharvil Nanavatic2031c42014-07-25 15:50:17 -070052 goto error;
53 }
54
Sharvil Nanavatifbf89082014-08-13 00:40:49 -070055 ret->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
56 if (ret->fd == INVALID_FD) {
Sharvil Nanavati44802762014-12-23 23:08:58 -080057 LOG_ERROR("%s unable to create socket: %s", __func__, strerror(errno));
Sharvil Nanavatic2031c42014-07-25 15:50:17 -070058 goto error;
59 }
60
61 int enable = 1;
Sharvil Nanavatifbf89082014-08-13 00:40:49 -070062 if (setsockopt(ret->fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) == -1) {
Sharvil Nanavati44802762014-12-23 23:08:58 -080063 LOG_ERROR("%s unable to set SO_REUSEADDR: %s", __func__, strerror(errno));
Sharvil Nanavatic2031c42014-07-25 15:50:17 -070064 goto error;
65 }
66
67 return ret;
68
69error:;
70 if (ret)
Sharvil Nanavatifbf89082014-08-13 00:40:49 -070071 close(ret->fd);
Zach Johnson384f8a92014-08-25 23:22:24 -070072 osi_free(ret);
Sharvil Nanavatic2031c42014-07-25 15:50:17 -070073 return NULL;
74}
75
Sharvil Nanavatiad3067b2014-08-21 18:13:46 -070076socket_t *socket_new_from_fd(int fd) {
77 assert(fd != INVALID_FD);
78
Zach Johnson384f8a92014-08-25 23:22:24 -070079 socket_t *ret = (socket_t *)osi_calloc(sizeof(socket_t));
Sharvil Nanavatiad3067b2014-08-21 18:13:46 -070080 if (!ret) {
Sharvil Nanavati44802762014-12-23 23:08:58 -080081 LOG_ERROR("%s unable to allocate memory for socket.", __func__);
Sharvil Nanavatiad3067b2014-08-21 18:13:46 -070082 return NULL;
83 }
84
85 ret->fd = fd;
86 return ret;
87}
88
Sharvil Nanavatic2031c42014-07-25 15:50:17 -070089void socket_free(socket_t *socket) {
90 if (!socket)
91 return;
92
93 socket_unregister(socket);
Sharvil Nanavatifbf89082014-08-13 00:40:49 -070094 close(socket->fd);
Zach Johnson384f8a92014-08-25 23:22:24 -070095 osi_free(socket);
Sharvil Nanavatic2031c42014-07-25 15:50:17 -070096}
97
98bool socket_listen(const socket_t *socket, port_t port) {
99 assert(socket != NULL);
100
101 struct sockaddr_in addr;
102 addr.sin_family = AF_INET;
103 addr.sin_addr.s_addr = 0;
104 addr.sin_port = htons(port);
Sharvil Nanavatifbf89082014-08-13 00:40:49 -0700105 if (bind(socket->fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
Sharvil Nanavati44802762014-12-23 23:08:58 -0800106 LOG_ERROR("%s unable to bind socket to port %u: %s", __func__, port, strerror(errno));
Sharvil Nanavatic2031c42014-07-25 15:50:17 -0700107 return false;
108 }
109
Sharvil Nanavatifbf89082014-08-13 00:40:49 -0700110 if (listen(socket->fd, 10) == -1) {
Sharvil Nanavati44802762014-12-23 23:08:58 -0800111 LOG_ERROR("%s unable to listen on port %u: %s", __func__, port, strerror(errno));
Sharvil Nanavatic2031c42014-07-25 15:50:17 -0700112 return false;
113 }
114
115 return true;
116}
117
118socket_t *socket_accept(const socket_t *socket) {
119 assert(socket != NULL);
120
Sharvil Nanavatifbf89082014-08-13 00:40:49 -0700121 int fd = accept(socket->fd, NULL, NULL);
122 if (fd == INVALID_FD) {
Sharvil Nanavati44802762014-12-23 23:08:58 -0800123 LOG_ERROR("%s unable to accept socket: %s", __func__, strerror(errno));
Sharvil Nanavatic2031c42014-07-25 15:50:17 -0700124 return NULL;
125 }
126
Zach Johnson384f8a92014-08-25 23:22:24 -0700127 socket_t *ret = (socket_t *)osi_calloc(sizeof(socket_t));
Sharvil Nanavatic2031c42014-07-25 15:50:17 -0700128 if (!ret) {
129 close(fd);
Sharvil Nanavati44802762014-12-23 23:08:58 -0800130 LOG_ERROR("%s unable to allocate memory for socket.", __func__);
Sharvil Nanavatic2031c42014-07-25 15:50:17 -0700131 return NULL;
132 }
133
Sharvil Nanavatifbf89082014-08-13 00:40:49 -0700134 ret->fd = fd;
Sharvil Nanavatic2031c42014-07-25 15:50:17 -0700135 return ret;
136}
137
138ssize_t socket_read(const socket_t *socket, void *buf, size_t count) {
139 assert(socket != NULL);
140 assert(buf != NULL);
141
Sharvil Nanavatifbf89082014-08-13 00:40:49 -0700142 return recv(socket->fd, buf, count, MSG_DONTWAIT);
Sharvil Nanavatic2031c42014-07-25 15:50:17 -0700143}
144
145ssize_t socket_write(const socket_t *socket, const void *buf, size_t count) {
146 assert(socket != NULL);
147 assert(buf != NULL);
148
Sharvil Nanavatifbf89082014-08-13 00:40:49 -0700149 return send(socket->fd, buf, count, MSG_DONTWAIT);
Sharvil Nanavatic2031c42014-07-25 15:50:17 -0700150}
151
Sharvil Nanavatiad3067b2014-08-21 18:13:46 -0700152ssize_t socket_write_and_transfer_fd(const socket_t *socket, const void *buf, size_t count, int fd) {
153 assert(socket != NULL);
154 assert(buf != NULL);
155
156 if (fd == INVALID_FD)
157 return socket_write(socket, buf, count);
158
159 struct msghdr msg;
160 struct iovec iov;
161 char control_buf[CMSG_SPACE(sizeof(int))];
162
163 iov.iov_base = (void *)buf;
164 iov.iov_len = count;
165
166 msg.msg_iov = &iov;
167 msg.msg_iovlen = 1;
168 msg.msg_control = control_buf;
169 msg.msg_controllen = sizeof(control_buf);
170 msg.msg_name = NULL;
171 msg.msg_namelen = 0;
172
173 struct cmsghdr *header = CMSG_FIRSTHDR(&msg);
174 header->cmsg_level = SOL_SOCKET;
175 header->cmsg_type = SCM_RIGHTS;
176 header->cmsg_len = CMSG_LEN(sizeof(int));
177 *(int *)CMSG_DATA(header) = fd;
178
179 ssize_t ret = sendmsg(socket->fd, &msg, MSG_DONTWAIT);
180 close(fd);
181 return ret;
182}
183
Sharvil Nanavati98bf85f2014-08-27 19:05:40 -0700184ssize_t socket_bytes_available(const socket_t *socket) {
185 assert(socket != NULL);
186
187 int size = 0;
188 if (ioctl(socket->fd, FIONREAD, &size) == -1)
189 return -1;
190 return size;
191}
192
Sharvil Nanavatifbf89082014-08-13 00:40:49 -0700193void socket_register(socket_t *socket, reactor_t *reactor, void *context, socket_cb read_cb, socket_cb write_cb) {
Sharvil Nanavatic2031c42014-07-25 15:50:17 -0700194 assert(socket != NULL);
Sharvil Nanavatic2031c42014-07-25 15:50:17 -0700195
196 // Make sure the socket isn't currently registered.
197 socket_unregister(socket);
198
Sharvil Nanavatic2031c42014-07-25 15:50:17 -0700199 socket->read_ready = read_cb;
200 socket->write_ready = write_cb;
201 socket->context = context;
202
Sharvil Nanavatifbf89082014-08-13 00:40:49 -0700203 void (*read_fn)(void *) = (read_cb != NULL) ? internal_read_ready : NULL;
204 void (*write_fn)(void *) = (write_cb != NULL) ? internal_write_ready : NULL;
Sharvil Nanavatic2031c42014-07-25 15:50:17 -0700205
Sharvil Nanavatifbf89082014-08-13 00:40:49 -0700206 socket->reactor_object = reactor_register(reactor, socket->fd, socket, read_fn, write_fn);
Sharvil Nanavatic2031c42014-07-25 15:50:17 -0700207}
208
209void socket_unregister(socket_t *socket) {
210 assert(socket != NULL);
211
Sharvil Nanavatifbf89082014-08-13 00:40:49 -0700212 if (socket->reactor_object)
213 reactor_unregister(socket->reactor_object);
214 socket->reactor_object = NULL;
Sharvil Nanavatic2031c42014-07-25 15:50:17 -0700215}
216
217static void internal_read_ready(void *context) {
218 assert(context != NULL);
219
220 socket_t *socket = (void *)context;
221 socket->read_ready(socket, socket->context);
222}
223
224static void internal_write_ready(void *context) {
225 assert(context != NULL);
226
227 socket_t *socket = (void *)context;
228 socket->write_ready(socket, socket->context);
229}