// Waits for incoming client connections, assumes GetState() == Created // true - success, false - failure (use GetLastError() for more details) bool TwoWayPipe::WaitForConnection() { _ASSERTE(m_state == Created); if (m_state != Created) return false; char inPipeName[PATH_MAX]; char outPipeName[PATH_MAX]; GetPipeName(inPipeName, m_id, "in"); GetPipeName(outPipeName, m_id, "out"); m_inboundPipe = open(inPipeName, O_RDONLY); if (m_inboundPipe == INVALID_PIPE) { return false; } m_outboundPipe = open(outPipeName, O_WRONLY); if (m_outboundPipe == INVALID_PIPE) { close(m_inboundPipe); m_inboundPipe = INVALID_PIPE; return false; } m_state = ServerConnected; return true; }
// Connects to a previously opened server side of the pipe. // Id is used to locate the pipe on the machine. // true - success, false - failure (use GetLastError() for more details) bool TwoWayPipe::Connect(DWORD id) { _ASSERTE(m_state == NotInitialized); if (m_state != NotInitialized) return false; m_id = id; char inPipeName[PATH_MAX]; char outPipeName[PATH_MAX]; //"in" and "out" are switched deliberately, because we're on the client GetPipeName(inPipeName, id, "out"); GetPipeName(outPipeName, id, "in"); // Pipe opening order is reversed compared to WaitForConnection() // in order to avaid deadlock. m_outboundPipe = open(outPipeName, O_WRONLY); if (m_outboundPipe == INVALID_PIPE) { return false; } m_inboundPipe = open(inPipeName, O_RDONLY); if (m_inboundPipe == INVALID_PIPE) { close(m_outboundPipe); m_outboundPipe = INVALID_PIPE; return false; } m_state = ClientConnected; return true; }
// Creates a server side of the pipe. // Id is used to create pipes names and uniquely identify the pipe on the machine. // true - success, false - failure (use GetLastError() for more details) bool TwoWayPipe::CreateServer(DWORD id) { _ASSERTE(m_state == NotInitialized); if (m_state != NotInitialized) return false; m_id = id; char inPipeName[PATH_MAX]; char outPipeName[PATH_MAX]; GetPipeName(inPipeName, id, "in"); GetPipeName(outPipeName, id, "out"); //TODO: REVIEW if S_IRWXU | S_IRWXG is the right access level in prof use if (mkfifo(inPipeName, S_IRWXU | S_IRWXG) == -1) { return false; } if (mkfifo(outPipeName, S_IRWXU | S_IRWXG) == -1) { remove(inPipeName); return false; } m_state = Created; return true; }
// Disconnect server or client side of the pipe. // true - success, false - failure (use GetLastError() for more details) bool TwoWayPipe::Disconnect() { if (m_outboundPipe != INVALID_PIPE && m_outboundPipe != 0) { close(m_outboundPipe); m_outboundPipe = INVALID_PIPE; } if (m_inboundPipe != INVALID_PIPE && m_inboundPipe != 0) { close(m_inboundPipe); m_inboundPipe = INVALID_PIPE; } if (m_state == ServerConnected || m_state == Created) { char inPipeName[PATH_MAX]; GetPipeName(inPipeName, m_id, "in"); remove(inPipeName); char outPipeName[PATH_MAX]; GetPipeName(outPipeName, m_id, "out"); remove(outPipeName); } m_state = NotInitialized; return true; }
shared_ptr<InterprocessIo> InterprocessServer::Connect() { shared_handle hPipe(CreateNamedPipe( GetPipeName(), PIPE_ACCESS_DUPLEX | // read/write access FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | // message type pipe PIPE_READMODE_MESSAGE | // message-read mode PIPE_WAIT, // non-blocking mode PIPE_UNLIMITED_INSTANCES, // max. instances BUF_SIZE, // output buffer size BUF_SIZE, // input buffer size NMPWAIT_USE_DEFAULT_WAIT, // client time-out NULL) // NULL DACL ); if(!hPipe) { return shared_ptr<InterprocessIo>(); } if(!ConnectNamedPipe(hPipe.get(), NULL) && (GetLastError()!=ERROR_PIPE_CONNECTED)) { return shared_ptr<InterprocessIo>(); } return shared_ptr<InterprocessIo>(new InterprocessIo(hPipe)); }
void InterprocessServer::OnCancel() { CreateFakeConnection(GetPipeName()); }