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 #include "QemuPipeStream.h" 17 #include <hardware/qemu_pipe.h> 18 #include <errno.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <unistd.h> 22 #include <string.h> 23 24 QemuPipeStream::QemuPipeStream(size_t bufSize) : 25 IOStream(bufSize), 26 m_sock(-1), 27 m_bufsize(bufSize), 28 m_buf(NULL) 29 { 30 } 31 32 QemuPipeStream::QemuPipeStream(int sock, size_t bufSize) : 33 IOStream(bufSize), 34 m_sock(sock), 35 m_bufsize(bufSize), 36 m_buf(NULL) 37 { 38 } 39 40 QemuPipeStream::~QemuPipeStream() 41 { 42 if (m_sock >= 0) { 43 flush(); 44 ::close(m_sock); 45 } 46 if (m_buf != NULL) { 47 free(m_buf); 48 } 49 } 50 51 52 int QemuPipeStream::connect(void) 53 { 54 m_sock = qemu_pipe_open("opengles"); 55 if (!valid()) return -1; 56 return 0; 57 } 58 59 void *QemuPipeStream::allocBuffer(size_t minSize) 60 { 61 size_t allocSize = (m_bufsize < minSize ? minSize : m_bufsize); 62 if (!m_buf) { 63 m_buf = (unsigned char *)malloc(allocSize); 64 } 65 else if (m_bufsize < allocSize) { 66 unsigned char *p = (unsigned char *)realloc(m_buf, allocSize); 67 if (p != NULL) { 68 m_buf = p; 69 m_bufsize = allocSize; 70 } else { 71 ERR("realloc (%d) failed\n", allocSize); 72 free(m_buf); 73 m_buf = NULL; 74 m_bufsize = 0; 75 } 76 } 77 78 return m_buf; 79 }; 80 81 int QemuPipeStream::commitBuffer(size_t size) 82 { 83 return writeFully(m_buf, size); 84 } 85 86 int QemuPipeStream::writeFully(const void *buf, size_t len) 87 { 88 //DBG(">> QemuPipeStream::writeFully %d\n", len); 89 if (!valid()) return -1; 90 if (!buf) { 91 if (len>0) ERR("QemuPipeStream::writeFully failed, buf=NULL, len %d", len); 92 return 0; 93 } 94 95 size_t res = len; 96 int retval = 0; 97 98 while (res > 0) { 99 ssize_t stat = ::write(m_sock, (const char *)(buf) + (len - res), res); 100 if (stat > 0) { 101 res -= stat; 102 continue; 103 } 104 if (stat == 0) { /* EOF */ 105 ERR("QemuPipeStream::writeFully failed: premature EOF\n"); 106 retval = -1; 107 break; 108 } 109 if (errno == EINTR) { 110 continue; 111 } 112 retval = stat; 113 ERR("QemuPipeStream::writeFully failed: %s\n", strerror(errno)); 114 break; 115 } 116 //DBG("<< QemuPipeStream::writeFully %d\n", len ); 117 return retval; 118 } 119 120 const unsigned char *QemuPipeStream::readFully(void *buf, size_t len) 121 { 122 //DBG(">> QemuPipeStream::readFully %d\n", len); 123 if (!valid()) return NULL; 124 if (!buf) { 125 if (len > 0) { 126 ERR("QemuPipeStream::readFully failed, buf=NULL, len %zu", len); 127 } 128 return NULL; // do not allow NULL buf in that implementation 129 } 130 size_t res = len; 131 while (res > 0) { 132 ssize_t stat = ::read(m_sock, (char *)(buf) + len - res, res); 133 if (stat == 0) { 134 // client shutdown; 135 return NULL; 136 } else if (stat < 0) { 137 if (errno == EINTR) { 138 continue; 139 } else { 140 ERR("QemuPipeStream::readFully failed (buf %p, len %zu" 141 ", res %zu): %s\n", buf, len, res, strerror(errno)); 142 return NULL; 143 } 144 } else { 145 res -= stat; 146 } 147 } 148 //DBG("<< QemuPipeStream::readFully %d\n", len); 149 return (const unsigned char *)buf; 150 } 151 152 const unsigned char *QemuPipeStream::read( void *buf, size_t *inout_len) 153 { 154 //DBG(">> QemuPipeStream::read %d\n", *inout_len); 155 if (!valid()) return NULL; 156 if (!buf) { 157 ERR("QemuPipeStream::read failed, buf=NULL"); 158 return NULL; // do not allow NULL buf in that implementation 159 } 160 161 int n = recv(buf, *inout_len); 162 163 if (n > 0) { 164 *inout_len = n; 165 return (const unsigned char *)buf; 166 } 167 168 //DBG("<< QemuPipeStream::read %d\n", *inout_len); 169 return NULL; 170 } 171 172 int QemuPipeStream::recv(void *buf, size_t len) 173 { 174 if (!valid()) return int(ERR_INVALID_SOCKET); 175 char* p = (char *)buf; 176 int ret = 0; 177 while(len > 0) { 178 int res = ::read(m_sock, p, len); 179 if (res > 0) { 180 p += res; 181 ret += res; 182 len -= res; 183 continue; 184 } 185 if (res == 0) { /* EOF */ 186 break; 187 } 188 if (errno == EINTR) 189 continue; 190 191 /* A real error */ 192 if (ret == 0) 193 ret = -1; 194 break; 195 } 196 return ret; 197 } 198