socket.cc revision d6121a37c579731b89348e618a823c53b938449a
1c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/****************************************************************************** 2c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * 3c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Copyright (C) 2014 Google, Inc. 4c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * 5c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Licensed under the Apache License, Version 2.0 (the "License"); 6c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * you may not use this file except in compliance with the License. 7c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * You may obtain a copy of the License at: 8c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * 9c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * http://www.apache.org/licenses/LICENSE-2.0 10c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * 11c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Unless required by applicable law or agreed to in writing, software 12c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * distributed under the License is distributed on an "AS IS" BASIS, 13c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * See the License for the specific language governing permissions and 15c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * limitations under the License. 16c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * 174918296afe1c667e9523cdfc799f558f7ebc2bfbWink Saville ******************************************************************************/ 18c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 19cebb2cc576c652dd642d7f419532ec04e0f59d7dNaveen Kalla#define LOG_TAG "bt_osi_socket" 20c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 212b7b6016c7a5f2c3ce9c7e623ea10a9fe9239dc2Paul Jensen#include "osi/include/socket.h" 22c9b81a0c05128694c617fcdd67e73821895822feWink Saville 23b449dc75ef4b9cb996c34a11e758f7e6ca193240Paul Jensen#include <asm/ioctls.h> 24c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville#include <assert.h> 25cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville#include <errno.h> 26c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville#include <netinet/in.h> 27c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville#include <string.h> 28c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville#include <sys/ioctl.h> 291a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu#include <sys/socket.h> 30cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville#include <unistd.h> 31c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 32cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville#include "osi/include/allocator.h" 33cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville#include "osi/include/log.h" 34c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville#include "osi/include/osi.h" 3596cce86cf08e37e0f09ed5057b1196e26b302743Robert Greenwalt#include "osi/include/reactor.h" 36cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville 371a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu// The IPv4 loopback address: 127.0.0.1 38af5593594070f825032be46dced573cd195956e1Robert Greenwaltstatic const in_addr_t LOCALHOST_ = 0x7f000001; 39cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville 409c180aedfc9f0d20525c0128487d3500e6c0a715Jason Monkstruct socket_t { 411a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu int fd; 42cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville reactor_object_t *reactor_object; 431a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu socket_cb read_ready; 44c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville socket_cb write_ready; 453fad7daba62dcb7aafc4adc7f8cc123726ed5a7cRobert Greenwalt void *context; // Not owned, do not free. 46b449dc75ef4b9cb996c34a11e758f7e6ca193240Paul Jensen}; 47a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 481a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yustatic void internal_read_ready(void *context); 49c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savillestatic void internal_write_ready(void *context); 5047588e2307efe45b21bf8384cf5fc49d167e2452Jordan Liu 51a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savillesocket_t *socket_new(void) { 52b449dc75ef4b9cb996c34a11e758f7e6ca193240Paul Jensen socket_t *ret = (socket_t *)osi_calloc(sizeof(socket_t)); 53c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 54c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville ret->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 551a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu if (ret->fd == INVALID_FD) { 56c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville LOG_ERROR(LOG_TAG, "%s unable to create socket: %s", __func__, strerror(errno)); 571a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu goto error; 58cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville } 5947588e2307efe45b21bf8384cf5fc49d167e2452Jordan Liu 60cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville int enable = 1; 612e2ec7d6844b8441df95b9ff38129e1e4a2d18f3Robert Greenwalt if (setsockopt(ret->fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) == -1) { 624c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu LOG_ERROR(LOG_TAG, "%s unable to set SO_REUSEADDR: %s", __func__, strerror(errno)); 630e776303ca82b5bec5db19bb44e0f13b0c7c6400Etan Cohen goto error; 64a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 651a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu 664c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu return ret; 67cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville 68cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Savilleerror:; 69c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville if (ret) 70cebb2cc576c652dd642d7f419532ec04e0f59d7dNaveen Kalla close(ret->fd); 712dde8b1659b1eb231e667bc19307ef294b627bebRobert Greenwalt osi_free(ret); 72ea763d93b231bccf7e476b625fa028bef7874bf8Robert Greenwalt return NULL; 73af5593594070f825032be46dced573cd195956e1Robert Greenwalt} 742b7b6016c7a5f2c3ce9c7e623ea10a9fe9239dc2Paul Jensen 75c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savillesocket_t *socket_new_from_fd(int fd) { 761a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu assert(fd != INVALID_FD); 77af5593594070f825032be46dced573cd195956e1Robert Greenwalt 78b5771d36210a751e6ec916556ad0f20fcb9b4288fionaxu socket_t *ret = (socket_t *)osi_calloc(sizeof(socket_t)); 79cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville 80cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville ret->fd = fd; 814c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu return ret; 82b449dc75ef4b9cb996c34a11e758f7e6ca193240Paul Jensen} 834c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu 844918296afe1c667e9523cdfc799f558f7ebc2bfbWink Savillevoid socket_free(socket_t *socket) { 85cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville if (!socket) 864c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu return; 87a02b6fd88953d783c32e6d7f84b7eddbc0d1faf1fionaxu 88f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu socket_unregister(socket); 89d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenka close(socket->fd); 90bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka osi_free(socket); 9176f43316a5a6082d601bffd4b6898d0bd81e11fcram} 924c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu 93c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savillebool socket_listen(const socket_t *socket, port_t port) { 94c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville assert(socket != NULL); 95c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 96c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville struct sockaddr_in addr; 9729c6659c8767212d23d417f2b7f032b6c0d82119Robert Greenwalt addr.sin_family = AF_INET; 981a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu addr.sin_addr.s_addr = htonl(LOCALHOST_); 991a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu addr.sin_port = htons(port); 10068f4f4a0bc8d4060b5775e7a24a97ea5b485989efionaxu if (bind(socket->fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { 1011a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu LOG_ERROR(LOG_TAG, "%s unable to bind socket to port %u: %s", __func__, port, strerror(errno)); 1021a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu return false; 10329c6659c8767212d23d417f2b7f032b6c0d82119Robert Greenwalt } 1041a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu 1051a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu if (listen(socket->fd, 10) == -1) { 1061a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu LOG_ERROR(LOG_TAG, "%s unable to listen on port %u: %s", __func__, port, strerror(errno)); 1071a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu return false; 1081a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu } 1091a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu 110c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville return true; 111c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville} 112c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 1130c3ec24396bb8c21b4d89f743b626c13dd35ba7bAmit Mahajansocket_t *socket_accept(const socket_t *socket) { 1141a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu assert(socket != NULL); 1151a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu 1161a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu int fd; 1171a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu OSI_NO_INTR(fd = accept(socket->fd, NULL, NULL)); 1181a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu if (fd == INVALID_FD) { 1191a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu LOG_ERROR(LOG_TAG, "%s unable to accept socket: %s", __func__, strerror(errno)); 1200e664d8c9ff3a1f2ab03d2bef4268615335ea1a2Jack Yu return NULL; 1211a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu } 1221a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu 1231a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu socket_t *ret = (socket_t *)osi_calloc(sizeof(socket_t)); 1241a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu 1251a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu ret->fd = fd; 1261a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu return ret; 127a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu} 128a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu 129a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yussize_t socket_read(const socket_t *socket, void *buf, size_t count) { 1300a39f581e11eb7b040a5412229164ef72044279fRobert Greenwalt assert(socket != NULL); 1311a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu assert(buf != NULL); 1321a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu 1331a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu ssize_t ret; 1341a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu OSI_NO_INTR(ret = recv(socket->fd, buf, count, MSG_DONTWAIT)); 1351a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu 1361a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu return ret; 1371a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu} 1381a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu 1391a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yussize_t socket_write(const socket_t *socket, const void *buf, size_t count) { 1401a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu assert(socket != NULL); 1411a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu assert(buf != NULL); 1421a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu 1431a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu ssize_t ret; 1441a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu OSI_NO_INTR(ret = send(socket->fd, buf, count, MSG_DONTWAIT)); 1451a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu 1461a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu return ret; 1471a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu} 1481a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu 1491a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yussize_t socket_write_and_transfer_fd(const socket_t *socket, const void *buf, size_t count, int fd) { 1501a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu assert(socket != NULL); 1511a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu assert(buf != NULL); 1521a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu 1531a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu if (fd == INVALID_FD) 1541a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu return socket_write(socket, buf, count); 1551a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu 1561a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu struct msghdr msg; 1571a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu struct iovec iov; 1581a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu char control_buf[CMSG_SPACE(sizeof(int))]; 1591a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu 1601a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu iov.iov_base = (void *)buf; 1611a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu iov.iov_len = count; 1621a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu 1633d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu msg.msg_iov = &iov; 1643d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu msg.msg_iovlen = 1; 1653d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu msg.msg_control = control_buf; 1663d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu msg.msg_controllen = sizeof(control_buf); 1673d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu msg.msg_name = NULL; 1683d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu msg.msg_namelen = 0; 1693d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu 1703d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu struct cmsghdr *header = CMSG_FIRSTHDR(&msg); 1713d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu header->cmsg_level = SOL_SOCKET; 1723d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu header->cmsg_type = SCM_RIGHTS; 1733d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu header->cmsg_len = CMSG_LEN(sizeof(int)); 1743d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu *(int *)CMSG_DATA(header) = fd; 1753d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu 1763d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu ssize_t ret; 1773d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu OSI_NO_INTR(ret = sendmsg(socket->fd, &msg, MSG_DONTWAIT)); 1783d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu 1793d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu close(fd); 1803d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu return ret; 1813d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu} 1823d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu 1833d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxussize_t socket_bytes_available(const socket_t *socket) { 1843d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu assert(socket != NULL); 1853d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu 1863d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu int size = 0; 1873d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu if (ioctl(socket->fd, FIONREAD, &size) == -1) 1883d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu return -1; 1893d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu return size; 1903d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu} 1913d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu 1923d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxuvoid socket_register(socket_t *socket, reactor_t *reactor, void *context, socket_cb read_cb, socket_cb write_cb) { 1933d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu assert(socket != NULL); 1943d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu 1953d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu // Make sure the socket isn't currently registered. 1963d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu socket_unregister(socket); 1973d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu 1983d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu socket->read_ready = read_cb; 1993d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu socket->write_ready = write_cb; 2003d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu socket->context = context; 2013d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu 2023d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu void (*read_fn)(void *) = (read_cb != NULL) ? internal_read_ready : NULL; 2033d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu void (*write_fn)(void *) = (write_cb != NULL) ? internal_write_ready : NULL; 2040d5e6cc0fdfb839d63abe1e7eb85eee1b5942108fionaxu 2050d5e6cc0fdfb839d63abe1e7eb85eee1b5942108fionaxu socket->reactor_object = reactor_register(reactor, socket->fd, socket, read_fn, write_fn); 2063d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu} 2073d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu 2083d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxuvoid socket_unregister(socket_t *socket) { 2093d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu assert(socket != NULL); 2103d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu 2113d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu if (socket->reactor_object) 2123d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu reactor_unregister(socket->reactor_object); 2133d8c0f70a6fa7a53fda3c5d592de0ac3aa247e3cfionaxu socket->reactor_object = NULL; 2141a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu} 2151a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu 2161a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yustatic void internal_read_ready(void *context) { 2171a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu assert(context != NULL); 2181a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu 2191a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu socket_t *socket = (void *)context; 2201a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu socket->read_ready(socket, socket->context); 2211a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu} 2221a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu 2231a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yustatic void internal_write_ready(void *context) { 2241a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu assert(context != NULL); 2251a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu 2261a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu socket_t *socket = (void *)context; 2271a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu socket->write_ready(socket, socket->context); 2281a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu} 2291a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu