1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <sys/socket.h>
18#include <netinet/in.h>
19#include <errno.h>
20#include <string.h>
21#include <unistd.h>
22#include <stddef.h>
23#include <stdio.h>
24#include "test_util.h"
25
26#ifdef __linux__
27#include <time.h>
28double now_secs(void)
29{
30    struct timespec  tm;
31    clock_gettime(CLOCK_MONOTONIC, &tm);
32    return (double)tm.tv_sec + (double)tm.tv_nsec/1e9;
33}
34#else
35#include <sys/time.h>
36double now_secs(void)
37{
38    struct timeval tv;
39    gettimeofday(&tv, NULL);
40    return tv.sec + (double)tv.usec/1e6;
41}
42#endif
43
44int
45pipe_openSocket( Pipe*  pipe, int port )
46{
47    static int           fd;
48    struct sockaddr_in  addr;
49
50    pipe->socket = -1;
51
52    fd = socket( AF_INET, SOCK_STREAM, 0 );
53    if (fd < 0) {
54        fprintf(stderr, "%s: Can't create socket!!\n", __FUNCTION__);
55        return -1;
56    }
57
58    memset(&addr, 0, sizeof(addr));
59    addr.sin_family      = AF_INET;
60    addr.sin_port        = htons(port);
61    addr.sin_addr.s_addr = htonl(0x0a000202);
62
63    if ( connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0 ) {
64        fprintf(stderr, "%s: Can't connect to tcp:local:%d: %s\n",
65                __FUNCTION__, port, strerror(errno));
66        close(fd);
67        return -1;
68    }
69
70    pipe->socket = fd;
71    return 0;
72}
73
74int
75pipe_openQemuPipe( Pipe*  pipe, const char* pipename )
76{
77    pipe->socket = qemu_pipe_open(pipename);
78    if (pipe->socket < 0) {
79        fprintf(stderr, "%s: Could not open '%s' pipe: %s\n", __FUNCTION__, pipename, strerror(errno));
80        return -1;
81    }
82    return 0;
83}
84
85int
86pipe_send( Pipe*  pipe, const void* buff, size_t  bufflen )
87{
88    int ret;
89    const uint8_t* ptr = buff;
90    while (bufflen > 0) {
91        ret = write(pipe->socket, ptr, bufflen);
92        if (ret < 0) {
93            if (errno == EINTR)
94                continue;
95            fprintf(stderr, "%s: error: %s\n", __FUNCTION__, strerror(errno));
96            return -1;
97        }
98        if (ret == 0) {
99            fprintf(stderr, "%s: disconnection!\n", __FUNCTION__);
100            return -1;
101        }
102        ptr     += ret;
103        bufflen -= ret;
104    }
105    return 0;
106}
107
108int
109pipe_recv( Pipe*  pipe, void* buff, size_t bufflen )
110{
111    int  ret;
112
113    for (;;) {
114        ret = read(pipe->socket, buff, bufflen);
115        if (ret < 0) {
116            if (errno == EINTR)
117                continue;
118            fprintf(stderr, "%s: error: %s\n", __FUNCTION__, strerror(errno));
119            return -1;
120        }
121        if (ret == 0) {
122            fprintf(stderr, "%s: disconnection!\n", __FUNCTION__);
123            return -1;
124        }
125        break;
126    }
127    return ret;
128}
129
130void
131pipe_close( Pipe*  pipe )
132{
133    if (pipe->socket >= 0) {
134        close(pipe->socket);
135        pipe->socket = -1;
136    }
137}
138