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 "Win32PipeStream.h" 17 18 #include <errno.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <unistd.h> 22 #include <string.h> 23 #include <windows.h> 24 25 #ifndef _WIN32 26 #error ONLY BUILD THIS SOURCE FILE FOR WINDOWS! 27 #endif 28 29 /* The official documentation states that the name of a given named 30 * pipe cannot be more than 256 characters long. 31 */ 32 #define NAMED_PIPE_MAX 256 33 34 Win32PipeStream::Win32PipeStream(size_t bufSize) : 35 SocketStream(bufSize), 36 m_pipe(INVALID_HANDLE_VALUE) 37 { 38 } 39 40 Win32PipeStream::Win32PipeStream(HANDLE pipe, size_t bufSize) : 41 SocketStream(-1, bufSize), 42 m_pipe(pipe) 43 { 44 } 45 46 Win32PipeStream::~Win32PipeStream() 47 { 48 if (m_pipe != INVALID_HANDLE_VALUE) { 49 CloseHandle(m_pipe); 50 m_pipe = INVALID_HANDLE_VALUE; 51 } 52 } 53 54 /* Initialize the pipe name corresponding to a given port 55 */ 56 static void 57 make_pipe_name(char *path, size_t pathlen, int port_number) 58 { 59 snprintf(path, pathlen, "\\\\.\\pipe\\qemu-gles-%d", port_number); 60 } 61 62 63 /* Technical note: Named pipes work differently from BSD Sockets. 64 * One does not create/bind a pipe, and collect a new handle each 65 * time a client connects with accept(). 66 * 67 * Instead, the server creates a new pipe instance each time it wants 68 * to get a new client connection, then calls ConnectNamedPipe() to 69 * wait for a connection. 70 * 71 * So listen() is a no-op, and accept() really creates the pipe handle. 72 * 73 * Also, connect() must create a pipe handle with CreateFile() and 74 * wait for a server instance with WaitNamedPipe() 75 */ 76 int Win32PipeStream::listen(char addrstr[MAX_ADDRSTR_LEN]) 77 { 78 m_port = GetCurrentProcessId(); 79 make_pipe_name(addrstr, MAX_ADDRSTR_LEN, m_port); 80 return 0; 81 } 82 83 SocketStream * Win32PipeStream::accept() 84 { 85 char path[NAMED_PIPE_MAX+1]; 86 SocketStream* clientStream; 87 HANDLE pipe; 88 89 make_pipe_name(path, sizeof(path), m_port); 90 91 pipe = ::CreateNamedPipe( 92 path, // pipe name 93 PIPE_ACCESS_DUPLEX, // read-write access 94 PIPE_TYPE_BYTE | // byte-oriented writes 95 PIPE_READMODE_BYTE | // byte-oriented reads 96 PIPE_WAIT, // blocking operations 97 PIPE_UNLIMITED_INSTANCES, // no limit on clients 98 4096, // input buffer size 99 4096, // output buffer size 100 0, // client time-out 101 NULL); // default security attributes 102 103 if (pipe == INVALID_HANDLE_VALUE) { 104 ERR("%s: CreateNamedPipe failed %d\n", __FUNCTION__, (int)GetLastError()); 105 return NULL; 106 } 107 108 // Stupid Win32 API design: If a client is already connected, then 109 // ConnectNamedPipe will return 0, and GetLastError() will return 110 // ERROR_PIPE_CONNECTED. This is not an error! It just means that the 111 // function didn't have to wait. 112 // 113 if (::ConnectNamedPipe(pipe, NULL) == 0 && GetLastError() != ERROR_PIPE_CONNECTED) { 114 ERR("%s: ConnectNamedPipe failed: %d\n", __FUNCTION__, (int)GetLastError()); 115 CloseHandle(pipe); 116 return NULL; 117 } 118 119 clientStream = new Win32PipeStream(pipe, m_bufsize); 120 return clientStream; 121 } 122 123 int Win32PipeStream::connect(const char* addr) 124 { 125 HANDLE pipe; 126 int tries = 10; 127 128 /* We're going to loop in order to wait for the pipe server to 129 * be setup properly. 130 */ 131 for (; tries > 0; tries--) { 132 pipe = ::CreateFile( 133 addr, // pipe name 134 GENERIC_READ | GENERIC_WRITE, // read & write 135 0, // no sharing 136 NULL, // default security attrs 137 OPEN_EXISTING, // open existing pipe 138 0, // default attributes 139 NULL); // no template file 140 141 /* If we have a valid pipe handle, break from the loop */ 142 if (pipe != INVALID_HANDLE_VALUE) { 143 break; 144 } 145 146 /* We can get here if the pipe is busy, i.e. if the server hasn't 147 * create a new pipe instance to service our request. In which case 148 * GetLastError() will return ERROR_PIPE_BUSY. 149 * 150 * If so, then use WaitNamedPipe() to wait for a decent time 151 * to try again. 152 */ 153 if (GetLastError() != ERROR_PIPE_BUSY) { 154 /* Not ERROR_PIPE_BUSY */ 155 ERR("%s: CreateFile failed: %d\n", __FUNCTION__, (int)GetLastError()); 156 errno = EINVAL; 157 return -1; 158 } 159 160 /* Wait for 5 seconds */ 161 if ( !WaitNamedPipe(addr, 5000) ) { 162 ERR("%s: WaitNamedPipe failed: %d\n", __FUNCTION__, (int)GetLastError()); 163 errno = EINVAL; 164 return -1; 165 } 166 } 167 168 m_pipe = pipe; 169 return 0; 170 } 171 172 /* Special buffer methods, since we can't use socket functions here */ 173 174 int Win32PipeStream::commitBuffer(size_t size) 175 { 176 if (m_pipe == INVALID_HANDLE_VALUE) 177 return -1; 178 179 size_t res = size; 180 int retval = 0; 181 182 while (res > 0) { 183 DWORD written; 184 if (! ::WriteFile(m_pipe, (const char *)m_buf + (size - res), res, &written, NULL)) { 185 retval = -1; 186 ERR("%s: failed: %d\n", __FUNCTION__, (int)GetLastError()); 187 break; 188 } 189 res -= written; 190 } 191 return retval; 192 } 193 194 const unsigned char *Win32PipeStream::readFully(void *buf, size_t len) 195 { 196 const unsigned char* ret = NULL; 197 198 if (m_pipe == INVALID_HANDLE_VALUE) 199 return NULL; 200 201 if (!buf) { 202 return NULL; // do not allow NULL buf in that implementation 203 } 204 205 size_t res = len; 206 while (res > 0) { 207 DWORD readcount = 0; 208 if (! ::ReadFile(m_pipe, (char *)buf + (len - res), res, &readcount, NULL) || readcount == 0) { 209 errno = (int)GetLastError(); 210 return NULL; 211 } 212 res -= readcount; 213 } 214 return (const unsigned char *)buf; 215 } 216 217 const unsigned char *Win32PipeStream::read( void *buf, size_t *inout_len) 218 { 219 size_t len = *inout_len; 220 DWORD readcount; 221 222 if (m_pipe == INVALID_HANDLE_VALUE) 223 return NULL; 224 225 if (!buf) { 226 return NULL; // do not allow NULL buf in that implementation 227 } 228 229 if (!::ReadFile(m_pipe, (char *)buf, len, &readcount, NULL)) { 230 errno = (int)GetLastError(); 231 return NULL; 232 } 233 234 *inout_len = (size_t)readcount; 235 return (const unsigned char *)buf; 236 } 237