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 91 size_t res = len; 92 int retval = 0; 93 94 while (res > 0) { 95 ssize_t stat = ::write(m_sock, (const char *)(buf) + (len - res), res); 96 if (stat > 0) { 97 res -= stat; 98 continue; 99 } 100 if (stat == 0) { /* EOF */ 101 ERR("QemuPipeStream::writeFully failed: premature EOF\n"); 102 retval = -1; 103 break; 104 } 105 if (errno == EINTR) { 106 continue; 107 } 108 retval = stat; 109 ERR("QemuPipeStream::writeFully failed: %s\n", strerror(errno)); 110 break; 111 } 112 //DBG("<< QemuPipeStream::writeFully %d\n", len ); 113 return retval; 114 } 115 116 const unsigned char *QemuPipeStream::readFully(void *buf, size_t len) 117 { 118 //DBG(">> QemuPipeStream::readFully %d\n", len); 119 if (!valid()) return NULL; 120 if (!buf) { 121 if (len>0) ERR("QemuPipeStream::readFully failed, buf=NULL, len %d", len); 122 return NULL; // do not allow NULL buf in that implementation 123 } 124 size_t res = len; 125 while (res > 0) { 126 ssize_t stat = ::read(m_sock, (char *)(buf) + len - res, len); 127 if (stat == 0) { 128 // client shutdown; 129 return NULL; 130 } else if (stat < 0) { 131 if (errno == EINTR) { 132 continue; 133 } else { 134 ERR("QemuPipeStream::readFully failed (buf %p): %s\n", 135 buf, strerror(errno)); 136 return NULL; 137 } 138 } else { 139 res -= stat; 140 } 141 } 142 //DBG("<< QemuPipeStream::readFully %d\n", len); 143 return (const unsigned char *)buf; 144 } 145 146 const unsigned char *QemuPipeStream::read( void *buf, size_t *inout_len) 147 { 148 //DBG(">> QemuPipeStream::read %d\n", *inout_len); 149 if (!valid()) return NULL; 150 if (!buf) { 151 ERR("QemuPipeStream::read failed, buf=NULL"); 152 return NULL; // do not allow NULL buf in that implementation 153 } 154 155 int n = recv(buf, *inout_len); 156 157 if (n > 0) { 158 *inout_len = n; 159 return (const unsigned char *)buf; 160 } 161 162 //DBG("<< QemuPipeStream::read %d\n", *inout_len); 163 return NULL; 164 } 165 166 int QemuPipeStream::recv(void *buf, size_t len) 167 { 168 if (!valid()) return int(ERR_INVALID_SOCKET); 169 char* p = (char *)buf; 170 int ret = 0; 171 while(len > 0) { 172 int res = ::read(m_sock, p, len); 173 if (res > 0) { 174 p += res; 175 ret += res; 176 len -= res; 177 continue; 178 } 179 if (res == 0) { /* EOF */ 180 break; 181 } 182 if (errno == EINTR) 183 continue; 184 185 /* A real error */ 186 if (ret == 0) 187 ret = -1; 188 break; 189 } 190 return ret; 191 } 192