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