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(unsigned short port) 77 { 78 // just save the port number for accept() 79 m_port = 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(unsigned short port) 124 { 125 char path[NAMED_PIPE_MAX+1]; 126 HANDLE pipe; 127 int tries = 10; 128 129 make_pipe_name(path, sizeof(path), port); 130 131 /* We're going to loop in order to wait for the pipe server to 132 * be setup properly. 133 */ 134 for (; tries > 0; tries--) { 135 pipe = ::CreateFile( 136 path, // pipe name 137 GENERIC_READ | GENERIC_WRITE, // read & write 138 0, // no sharing 139 NULL, // default security attrs 140 OPEN_EXISTING, // open existing pipe 141 0, // default attributes 142 NULL); // no template file 143 144 /* If we have a valid pipe handle, break from the loop */ 145 if (pipe != INVALID_HANDLE_VALUE) { 146 break; 147 } 148 149 /* We can get here if the pipe is busy, i.e. if the server hasn't 150 * create a new pipe instance to service our request. In which case 151 * GetLastError() will return ERROR_PIPE_BUSY. 152 * 153 * If so, then use WaitNamedPipe() to wait for a decent time 154 * to try again. 155 */ 156 if (GetLastError() != ERROR_PIPE_BUSY) { 157 /* Not ERROR_PIPE_BUSY */ 158 ERR("%s: CreateFile failed: %d\n", __FUNCTION__, (int)GetLastError()); 159 errno = EINVAL; 160 return -1; 161 } 162 163 /* Wait for 5 seconds */ 164 if ( !WaitNamedPipe(path, 5000) ) { 165 ERR("%s: WaitNamedPipe failed: %d\n", __FUNCTION__, (int)GetLastError()); 166 errno = EINVAL; 167 return -1; 168 } 169 } 170 171 m_pipe = pipe; 172 return 0; 173 } 174 175 /* Special buffer methods, since we can't use socket functions here */ 176 177 int Win32PipeStream::commitBuffer(size_t size) 178 { 179 if (m_pipe == INVALID_HANDLE_VALUE) 180 return -1; 181 182 size_t res = size; 183 int retval = 0; 184 185 while (res > 0) { 186 DWORD written; 187 if (! ::WriteFile(m_pipe, (const char *)m_buf + (size - res), res, &written, NULL)) { 188 retval = -1; 189 ERR("%s: failed: %d\n", __FUNCTION__, (int)GetLastError()); 190 break; 191 } 192 res -= written; 193 } 194 return retval; 195 } 196 197 const unsigned char *Win32PipeStream::readFully(void *buf, size_t len) 198 { 199 const unsigned char* ret = NULL; 200 201 if (m_pipe == INVALID_HANDLE_VALUE) 202 return NULL; 203 204 if (!buf) { 205 return NULL; // do not allow NULL buf in that implementation 206 } 207 208 size_t res = len; 209 while (res > 0) { 210 DWORD readcount = 0; 211 if (! ::ReadFile(m_pipe, (char *)buf + (len - res), res, &readcount, NULL) || readcount == 0) { 212 errno = (int)GetLastError(); 213 return NULL; 214 } 215 res -= readcount; 216 } 217 return (const unsigned char *)buf; 218 } 219 220 const unsigned char *Win32PipeStream::read( void *buf, size_t *inout_len) 221 { 222 size_t len = *inout_len; 223 DWORD readcount; 224 225 if (m_pipe == INVALID_HANDLE_VALUE) 226 return NULL; 227 228 if (!buf) { 229 return NULL; // do not allow NULL buf in that implementation 230 } 231 232 if (!::ReadFile(m_pipe, (char *)buf, len, &readcount, NULL)) { 233 errno = (int)GetLastError(); 234 return NULL; 235 } 236 237 *inout_len = (size_t)readcount; 238 return (const unsigned char *)buf; 239 } 240