blob: 2c7cf56d25e8b1c56462f881bc1e9317f59b8c46 [file] [log] [blame]
Roger Meierd1bf5d02012-04-11 21:38:56 +00001/*
2* Licensed to the Apache Software Foundation (ASF) under one
3* or more contributor license agreements. See the NOTICE file
4* distributed with this work for additional information
5* regarding copyright ownership. The ASF licenses this file
6* to you under the Apache License, Version 2.0 (the
7* "License"); you may not use this file except in compliance
8* with the License. You may obtain a copy of the License at
9*
10* http://www.apache.org/licenses/LICENSE-2.0
11*
12* Unless required by applicable law or agreed to in writing,
13* software distributed under the License is distributed on an
14* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15* KIND, either express or implied. See the License for the
16* specific language governing permissions and limitations
17* under the License.
18*/
19
20#ifdef _WIN32
21
22#include "TTransportException.h"
23#include "TPipe.h"
24
25namespace apache { namespace thrift { namespace transport {
26
27using namespace std;
28
29/**
30* TPipe implementation.
31*/
32
33//---- Constructors ----
34TPipe::TPipe(HANDLE hpipe) :
35 pipename_(""),
36 hPipe_(hpipe),
37 TimeoutSeconds_(3),
38 isAnonymous(false)
39{}
40
41TPipe::TPipe(string pipename) :
42 pipename_(pipename),
43 hPipe_(INVALID_HANDLE_VALUE),
44 TimeoutSeconds_(3),
45 isAnonymous(false)
46{}
47
48TPipe::TPipe(HANDLE hPipeRd, HANDLE hPipeWrt) :
49 pipename_(""),
50 hPipe_(hPipeRd),
51 hPipeWrt_(hPipeWrt),
52 TimeoutSeconds_(3),
53 isAnonymous(true)
54{}
55
56 TPipe::TPipe() :
57 pipename_(""),
58 hPipe_(INVALID_HANDLE_VALUE),
59 TimeoutSeconds_(3)
60{}
61
62//---- Destructor ----
63TPipe::~TPipe() {
64 close();
65}
66
67
68bool TPipe::isOpen() {
69 return (hPipe_ != INVALID_HANDLE_VALUE);
70}
71
72//---------------------------------------------------------
73// Transport callbacks
74//---------------------------------------------------------
75
76bool TPipe::peek() {
77 if (!isOpen()) {
78 return false;
79 }
80 DWORD bytesavail = 0;
81 int PeekRet = 0;
82 PeekRet = PeekNamedPipe(hPipe_, NULL, 0, NULL, &bytesavail, NULL);
83 return (PeekRet != 0 && bytesavail > 0);
84}
85
86void TPipe::open() {
87 if (isOpen()) {
88 return;
89 }
90
91 int SleepInterval = 500; //ms
92 int retries = TimeoutSeconds_ * 1000 / SleepInterval;
93 for(int i=0; i<retries; i++)
94 {
95 hPipe_ = CreateFile(
96 pipename_.c_str(),
97 GENERIC_READ | GENERIC_WRITE,
98 0, // no sharing
99 NULL, // default security attributes
100 OPEN_EXISTING, // opens existing pipe
101 0, // default attributes
102 NULL); // no template file
103
104 if (hPipe_ == INVALID_HANDLE_VALUE)
105 sleep(SleepInterval);
106 else
107 break;
108 }
109 if (hPipe_ == INVALID_HANDLE_VALUE)
110 throw TTransportException(TTransportException::NOT_OPEN, "Unable to open pipe");
111
112 // The pipe connected; change to message-read mode.
113 DWORD dwMode = PIPE_READMODE_MESSAGE;
114 int fSuccess = SetNamedPipeHandleState(
115 hPipe_, // pipe handle
116 &dwMode, // new pipe mode
117 NULL, // don't set maximum bytes
118 NULL); // don't set maximum time
119 if (fSuccess == 0)
120 {
121 throw TTransportException(TTransportException::NOT_OPEN, "SetNamedPipeHandleState failed");
122 close();
123 }
124}
125
126
127void TPipe::close() {
128 if (isOpen())
129 {
130 CloseHandle(hPipe_);
131 hPipe_ = INVALID_HANDLE_VALUE;
132 }
133}
134
135uint32_t TPipe::read(uint8_t* buf, uint32_t len) {
136 if (!isOpen())
137 throw TTransportException(TTransportException::NOT_OPEN, "Called read on non-open pipe");
138
139 DWORD cbRead;
140 int fSuccess = ReadFile(
141 hPipe_, // pipe handle
142 buf, // buffer to receive reply
143 len, // size of buffer
144 &cbRead, // number of bytes read
145 NULL); // not overlapped
146
147 if ( !fSuccess && GetLastError() != ERROR_MORE_DATA )
148 return 0; // No more data, possibly because client disconnected.
149
150 return cbRead;
151}
152
153void TPipe::write(const uint8_t* buf, uint32_t len) {
154 if (!isOpen())
155 throw TTransportException(TTransportException::NOT_OPEN, "Called write on non-open pipe");
156
157 HANDLE WritePipe = isAnonymous? hPipeWrt_: hPipe_;
158 DWORD cbWritten;
159 int fSuccess = WriteFile(
160 WritePipe, // pipe handle
161 buf, // message
162 len, // message length
163 &cbWritten, // bytes written
164 NULL); // not overlapped
165
166 if ( !fSuccess)
167 throw TTransportException(TTransportException::NOT_OPEN, "Write to pipe failed");
168}
169
170
171//---------------------------------------------------------
172// Accessors
173//---------------------------------------------------------
174
175string TPipe::getPipename() {
176 return pipename_;
177}
178
179void TPipe::setPipename(std::string pipename) {
180 pipename_ = pipename;
181}
182
183HANDLE TPipe::getPipeHandle() {
184 return hPipe_;
185}
186
187void TPipe::setPipeHandle(HANDLE pipehandle) {
188 hPipe_ = pipehandle;
189}
190
191HANDLE TPipe::getWrtPipeHandle() {
192 return hPipeWrt_;
193}
194
195void TPipe::setWrtPipeHandle(HANDLE pipehandle) {
196 hPipeWrt_ = pipehandle;
197}
198
199long TPipe::getConnectTimeout() {
200 return TimeoutSeconds_;
201}
202
203void TPipe::setConnectTimeout(long seconds) {
204 TimeoutSeconds_ = seconds;
205}
206
207}}} // apache::thrift::transport
208
209#endif //_WIN32