1a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine/* 2a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine * Copyright (C) 2010 The Android Open Source Project 3a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine * 4a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine * Licensed under the Apache License, Version 2.0 (the "License"); 5a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine * you may not use this file except in compliance with the License. 6a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine * You may obtain a copy of the License at 7a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine * 8a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine * http://www.apache.org/licenses/LICENSE-2.0 9a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine * 10a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine * Unless required by applicable law or agreed to in writing, software 11a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine * distributed under the License is distributed on an "AS IS" BASIS, 12a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine * See the License for the specific language governing permissions and 14a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine * limitations under the License. 15a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine */ 16a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine 17a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine/* 18a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine * Contains helper routines dealing with syncronous access to a non-blocking 19a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine * sokets. 20a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine */ 21a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine 22a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine#include "qemu-common.h" 23a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine#include "errno.h" 24d413fa5f2916a2a46494edb320340486b262644cDavid 'Digit' Turner#include "android/iolooper.h" 25cc330d4169441727fecf1da08aee806fc021c4e2David 'Digit' Turner#include "android/sockets.h" 26a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine#include "android/utils/debug.h" 27a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine#include "android/sync-utils.h" 289411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine#include "android/utils/system.h" 29a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine 30a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine#define D(...) do { if (VERBOSE_CHECK(init)) dprint(__VA_ARGS__); } while (0) 31a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine 32a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkinestruct SyncSocket { 33a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine // Helper for performing synchronous I/O on the socket. 34a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine IoLooper* iolooper; 35a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine 36a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine /* Opened socket handle. */ 37a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine int fd; 38a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine}; 39a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine 40a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir ChtchetkineSyncSocket* 419411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkinesyncsocket_init(int fd) 429411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine{ 439411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine SyncSocket* sync_socket; 449411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine ANEW0(sync_socket); 459411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine 469411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine socket_set_nonblock(fd); 479411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine sync_socket->iolooper = iolooper_new(); 489411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine sync_socket->fd = fd; 499411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine 509411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine return sync_socket; 519411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine} 529411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine 539411a562e1ab772732a4d5147c9103a638837c82Vladimir ChtchetkineSyncSocket* 54a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkinesyncsocket_connect(int fd, SockAddress* sockaddr, int timeout) 55a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine{ 569411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine IoLooper* looper; 57a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine int connect_status; 589411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine SyncSocket* sync_socket = NULL; 59a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine 60a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine socket_set_nonblock(fd); 61a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine 62a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine for(;;) { 63a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine connect_status = socket_connect(fd, sockaddr); 64a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine if (connect_status >= 0) { 65a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine // Connected. Create IoLooper for the helper. 66a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine looper = iolooper_new(); 67a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine break; 68a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine } 69a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine 70a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine if (errno == EINPROGRESS || errno == EAGAIN || errno == EWOULDBLOCK) { 71a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine // Connection is in progress. Wait till it's finished. 72a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine looper = iolooper_new(); 73a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine iolooper_add_write(looper, fd); 74a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine connect_status = iolooper_wait(looper, timeout); 75a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine if (connect_status > 0) { 76a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine iolooper_del_write(looper, fd); 7717ecca637df2f573edc3ecb8246c0e38a5b32465Vladimir Chtchetkine break; 78a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine } else { 79a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine iolooper_free(looper); 80a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine return NULL; 81a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine } 82af81d7432594d8459c4fb9f76c5e8a981f69a94cDavid 'Digit' Turner } else { 83a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine return NULL; 84a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine } 85a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine } 86a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine 87a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine // We're now connected. Lets initialize SyncSocket instance 88a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine // for this connection. 89a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine sync_socket = malloc(sizeof(SyncSocket)); 90a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine if (sync_socket == NULL) { 91a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine derror("PANIC: not enough memory\n"); 92a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine exit(1); 93a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine } 94a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine 95a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine sync_socket->iolooper = looper; 96a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine sync_socket->fd = fd; 97a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine 98a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine return sync_socket; 99a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine} 100a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine 101a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkinevoid 102a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkinesyncsocket_close(SyncSocket* ssocket) 103a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine{ 104a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine if (ssocket != NULL && ssocket->fd >= 0) { 105a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine if (ssocket->iolooper != NULL) { 106a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine iolooper_reset(ssocket->iolooper); 107a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine } 108a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine socket_close(ssocket->fd); 109a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine ssocket->fd = -1; 110a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine } 111a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine} 112a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine 113a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkinevoid 114a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkinesyncsocket_free(SyncSocket* ssocket) 115a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine{ 116a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine if (ssocket != NULL) { 117a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine if (ssocket->iolooper != NULL) { 118a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine iolooper_free(ssocket->iolooper); 119a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine } 120a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine free(ssocket); 121a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine } 122a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine} 123a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine 124a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkineint 125a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkinesyncsocket_start_read(SyncSocket* ssocket) 126a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine{ 127a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine if (ssocket == NULL || ssocket->fd < 0 || ssocket->iolooper == NULL) { 128a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine errno = EINVAL; 129a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine return -1; 130a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine } 131a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine iolooper_add_read(ssocket->iolooper, ssocket->fd); 132a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine return 0; 133a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine} 134a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine 135a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkineint 136a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkinesyncsocket_stop_read(SyncSocket* ssocket) 137a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine{ 138a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine if (ssocket == NULL || ssocket->fd < 0 || ssocket->iolooper == NULL) { 139a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine errno = EINVAL; 140a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine return -1; 141a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine } 142a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine iolooper_del_read(ssocket->iolooper, ssocket->fd); 143a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine return 0; 144a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine} 145a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine 146a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkineint 147d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkinesyncsocket_start_write(SyncSocket* ssocket) 148d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine{ 149d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine if (ssocket == NULL || ssocket->fd < 0 || ssocket->iolooper == NULL) { 150d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine errno = EINVAL; 151d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine return -1; 152d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine } 153d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine iolooper_add_write(ssocket->iolooper, ssocket->fd); 154d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine return 0; 155d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine} 156d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine 157d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkineint 158d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkinesyncsocket_stop_write(SyncSocket* ssocket) 159d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine{ 160d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine if (ssocket == NULL || ssocket->fd < 0 || ssocket->iolooper == NULL) { 161d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine errno = EINVAL; 162d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine return -1; 163d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine } 164d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine iolooper_del_write(ssocket->iolooper, ssocket->fd); 165d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine return 0; 166d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine} 167d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine 168d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkinessize_t 169a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkinesyncsocket_read_absolute(SyncSocket* ssocket, 170a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine void* buf, 1710d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine size_t size, 172a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine int64_t deadline) 173a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine{ 174a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine int ret; 175a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine 176a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine if (ssocket == NULL || ssocket->fd < 0 || ssocket->iolooper == NULL) { 177a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine errno = EINVAL; 178a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine return -1; 179a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine } 180a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine 181a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine ret = iolooper_wait_absolute(ssocket->iolooper, deadline); 182a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine if (ret > 0) { 183a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine if (!iolooper_is_read(ssocket->iolooper, ssocket->fd)) { 184a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine D("%s: Internal error, iolooper_is_read() not set!", __FUNCTION__); 185a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine return -1; 186a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine } 187af81d7432594d8459c4fb9f76c5e8a981f69a94cDavid 'Digit' Turner ret = socket_recv(ssocket->fd, buf, size); 188d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine } else if (ret == 0) { 189d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine // Timed out 190d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine errno = ETIMEDOUT; 191d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine ret = -1; 192a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine } 193a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine return ret; 194a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine} 195a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine 196d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkinessize_t 1970d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkinesyncsocket_read(SyncSocket* ssocket, void* buf, size_t size, int timeout) 198a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine{ 199a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine return syncsocket_read_absolute(ssocket, buf, size, iolooper_now() + timeout); 200a8fc4913fb7a4f834a5b9084e86a4a2e3dfd7e0cVladimir Chtchetkine} 2010d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine 202d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkinessize_t 203d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkinesyncsocket_write_absolute(SyncSocket* ssocket, 204d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine const void* buf, 205d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine size_t size, 206d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine int64_t deadline) 207d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine{ 208d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine int ret; 209d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine size_t written = 0; 210d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine 211d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine if (ssocket == NULL || ssocket->fd < 0 || ssocket->iolooper == NULL) { 212d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine errno = EINVAL; 213d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine return -1; 214d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine } 215d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine 216d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine do { 217d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine ret = iolooper_wait_absolute(ssocket->iolooper, deadline); 218d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine if (ret < 0) { 219d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine return ret; 220d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine } else if (ret == 0) { 221d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine // Timeout. 222d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine errno = ETIMEDOUT; 223d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine return -1; 224d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine } 225d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine if (!iolooper_is_write(ssocket->iolooper, ssocket->fd)) { 226d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine D("%s: Internal error, iolooper_is_write() not set!", __FUNCTION__); 227d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine return -1; 228d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine } 229d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine 230af81d7432594d8459c4fb9f76c5e8a981f69a94cDavid 'Digit' Turner ret = socket_send(ssocket->fd, (const char*)buf + written, size - written); 231d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine if (ret > 0) { 232d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine written += ret; 233d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine } else if (ret < 0) { 234d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine if (errno != EAGAIN && errno != EWOULDBLOCK) { 235d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine return -1; 236d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine } 237d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine } else { 238d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine // Disconnected. 239d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine errno = ECONNRESET; 240d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine return -1; 241d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine } 242d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine } while (written < size); 243d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine return (int)written; 244d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine} 245d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine 246d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkinessize_t 247d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkinesyncsocket_write(SyncSocket* ssocket, const void* buf, size_t size, int timeout) 248d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine{ 249d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine return syncsocket_write_absolute(ssocket, buf, size, iolooper_now() + timeout); 250d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine} 251d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine 252d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkinessize_t 2530d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkinesyncsocket_read_line_absolute(SyncSocket* ssocket, 2540d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine char* buffer, 2550d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine size_t size, 2560d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine int64_t deadline) 2570d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine{ 2580d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine size_t read_chars = 0; 2590d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine 2600d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine while (read_chars < size) { 2610d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine char ch; 2620d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine int ret = syncsocket_read_absolute(ssocket, &ch, 1, deadline); 2630d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine if (ret <= 0) { 2640d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine return ret; 2650d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine } 2660d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine buffer[read_chars++] = ch; 2670d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine if (ch == '\n') { 268d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine return read_chars; 2690d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine } 2700d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine } 2710d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine 2720d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine /* Not enough room in the input buffer!*/ 2730d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine errno = ENOMEM; 2740d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine return -1; 2750d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine} 2760d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine 277d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkinessize_t 2780d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkinesyncsocket_read_line(SyncSocket* ssocket, char* buffer, size_t size, int timeout) 2790d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine{ 2800d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine return syncsocket_read_line_absolute(ssocket, buffer, size, 2810d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine iolooper_now() + timeout); 2820d4c88288c6109eec4c4b4801519809f0c23cd46Vladimir Chtchetkine} 283e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine 284e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkineint 285e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkinesyncsocket_get_socket(SyncSocket* ssocket) 286e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine{ 287e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine return (ssocket != NULL) ? ssocket->fd : -1; 288e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine} 289