protected Ipc.ResponseCode SendReceive(Ipc.Command commandId, byte[] data, int dataLength, out byte[] response) { CheckConnected(); ushort messageId = _nextMessageId; _nextMessageId = (ushort)(_nextMessageId == UInt16.MaxValue ? 1 : _nextMessageId + 1); BitConverter.GetBytes((ushort)commandId).CopyTo(data, 0); BitConverter.GetBytes(messageId).CopyTo(data, 2); BitConverter.GetBytes((ushort)(dataLength - 6)).CopyTo(data, 4); _pipe.Write(data, 0, dataLength); _pipe.Flush(); if (((ushort)commandId & Ipc.NO_RESPONSE_COMMAND) != 0) { response = null; return(Ipc.ResponseCode.Ok); } var header = new byte[6]; var tEnd = DateTime.Now.AddMilliseconds(ResponseTimeout); while (DateTime.Now <= tEnd) { // read 6 byte header int cnt = 0; while (cnt < header.Length) { var readDoneEvent = new ManualResetEvent(false); int newCnt = 0; Exception endReadEx = null; _pipe.BeginRead(header, cnt, header.Length - cnt, ar => { try { newCnt = _pipe.EndRead(ar); } catch (Exception ex) { endReadEx = ex; } readDoneEvent.Set(); }, null); if (!readDoneEvent.WaitOne(ResponseTimeout)) { Disconnect(); Connect(); throw new TimeoutException(cnt == 0 ? String.Format("No response for IPC message from {0} for command {1}", AppName, commandId) : String.Format("Timeout for IPC message from {0} for command {1}", AppName, commandId)); } if (endReadEx != null) { throw new IpcException(endReadEx.Message, endReadEx); } if (newCnt == 0) // end of stream { throw new IpcException("Connection closed unexpected"); } cnt += newCnt; } Ipc.ResponseCode responseCode = (Ipc.ResponseCode)BitConverter.ToUInt16(header, 0); ushort responseMessageId = BitConverter.ToUInt16(header, 2); // for future use to allow parallel messages from a single client ushort responseLength = BitConverter.ToUInt16(header, 4); response = new byte[responseLength]; if (responseLength > 0) { cnt = 0; while (cnt < response.Length) { var readDoneEvent = new ManualResetEvent(false); int newCnt = 0; Exception endReadEx = null; _pipe.BeginRead(response, cnt, response.Length - cnt, ar => { try { newCnt = _pipe.EndRead(ar); } catch (Exception ex) { endReadEx = ex; } readDoneEvent.Set(); }, null); if (!readDoneEvent.WaitOne(ResponseTimeout)) { Disconnect(); Connect(); throw new TimeoutException(String.Format("Timeout for IPC message from {0} for command {1}", AppName, commandId)); } if (endReadEx != null) { throw new IpcException(endReadEx.Message, endReadEx); } if (newCnt == 0) // end of stream { throw new IpcException("Connection closed unexpected"); } cnt += newCnt; } } if (responseMessageId == messageId) { if (responseCode == Ipc.ResponseCode.ServerException) { int offset = 0; var message = Ipc.BytesToString(response, ref offset); var typeName = Ipc.BytesToString(response, ref offset); throw new IpcException(String.Format("A IPC server exception of type {0} was thrown:\n{1}", typeName, message)); } return(responseCode); } } throw new TimeoutException(String.Format("No response for IPC message from {0} for command {1}", AppName, commandId)); }
private void WaitForConnectionCallback(IAsyncResult ar) { try { // finish async wait var pipe = (NamedPipeServerStream)ar.AsyncState; pipe.EndWaitForConnection(ar); // start another pipe for the next client OpenNewPipe(); try { var header = new byte[6]; while (true) { // read 6 byte header int cnt = 0; while (cnt < header.Length) { int newCnt = pipe.Read(header, cnt, header.Length - cnt); if (newCnt == 0) // end of stream { return; } cnt += newCnt; } Ipc.Command commandId = (Ipc.Command)BitConverter.ToUInt16(header, 0); ushort messageId = BitConverter.ToUInt16(header, 2); // for future use to allow parallel messages from a single client ushort dataLength = BitConverter.ToUInt16(header, 4); var data = new byte[dataLength]; if (dataLength > 0) { cnt = 0; while (cnt < data.Length) { int newCnt = pipe.Read(data, cnt, data.Length - cnt); if (newCnt == 0) // end of stream { return; } cnt += newCnt; } } var response = new byte[1024]; int responseOffset = 6; Ipc.ResponseCode responseCode; try { responseCode = ProcessCommand(commandId, data, 0, dataLength, ref response, ref responseOffset); } catch (Exception ex) { responseCode = Ipc.ResponseCode.ServerException; responseOffset = 6; Ipc.StringToBytes(ex.Message, response, ref responseOffset); Ipc.StringToBytes(ex.GetType().FullName, response, ref responseOffset); } if (((ushort)commandId & Ipc.NO_RESPONSE_COMMAND) == 0) { // send response BitConverter.GetBytes((ushort)responseCode).CopyTo(response, 0); BitConverter.GetBytes(messageId).CopyTo(response, 2); BitConverter.GetBytes((ushort)(responseOffset - 6)).CopyTo(response, 4); pipe.Write(response, 0, responseOffset); } } } finally { lock (_serverPipes) { _serverPipes.Remove(pipe); pipe.Close(); } } } catch (Exception) { } }