1 /*****************************************************************************/
2 /* Software Testing Automation Framework (STAF) */
3 /* (C) Copyright IBM Corp. 2001 */
4 /* */
5 /* This software is licensed under the Eclipse Public License (EPL) V1.0. */
6 /*****************************************************************************/
7
8 #include "STAFOSTypes.h"
9 #include "STAFLocalConnection.h"
10 #include "STAFException.h"
11
12 #ifdef DEBUG_LOCAL_CONNECTION
13 #undef sleep
14 #include "STAF_iostream.h"
15 #include "STAFThread.h"
16 #define MYTID STAFThreadGetCurrentThreadID()
17 #endif
18
19 #define CHECKCONNECT(string) if (rc) {\
20 STAFConnectionConnectException connectError(string, rc);\
21 THROW_STAF_EXCEPTION(connectError);}
22
23 #define CHECKIO(string) if (rc) {\
24 STAFConnectionIOException ioError(string, rc);\
25 THROW_STAF_EXCEPTION(ioError);}
26
create(STAFString localName)27 STAFConnAllocInfo STAFLocalConnection::create(STAFString localName)
28 {
29 return STAFConnAllocInfo(new STAFLocalConnection(localName),
30 &freeLocalConnection);
31 }
32
33
STAFLocalConnection(HPIPE pipeHandle)34 STAFLocalConnection::STAFLocalConnection(HPIPE pipeHandle)
35 {
36 return STAFConnAllocInfo(new STAFLocalConnection(pipeHandle),
37 &freeLocalConnection);
38 }
39
40
STAFLocalConnection(STAFString localName)41 STAFLocalConnection::STAFLocalConnection(STAFString localName)
42 : STAFConnection(kLocal, kClient)
43 {
44 APIRET rc = 0;
45 ULONG openAction;
46 STAFString pipeName(STAFString("\\PIPE\\") + localName);
47 STAFStringBufferPtr pipeNameBuf = pipeName.toCurrentCodePage();
48
49 rc = DosOpen((PSZ)pipeNameBuf->buffer(), &fPipeHandle, &openAction, 0, 0,
50 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
51 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE, 0);
52
53 while ((rc == ERROR_PIPE_BUSY) || (rc == ERROR_SEM_TIMEOUT))
54 {
55 rc = DosWaitNPipe((PSZ)pipeNameBuf->buffer(), 100);
56
57 if (!rc)
58 {
59 rc = DosOpen((PSZ)pipeNameBuf->buffer(), &fPipeHandle, &openAction,
60 0, 0, OPEN_ACTION_FAIL_IF_NEW |
61 OPEN_ACTION_OPEN_IF_EXISTS,
62 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE, 0);
63 }
64 }
65
66 CHECKCONNECT("DosOpen");
67 }
68
69
STAFLocalConnection(HPIPE pipeHandle)70 STAFLocalConnection::STAFLocalConnection(HPIPE pipeHandle)
71 : STAFConnection(kLocal, kServer), fPipeHandle(pipeHandle)
72 {
73 /* Do Nothing */
74 }
75
76
read(void * buffer,unsigned int size)77 void STAFLocalConnection::read(void *buffer, unsigned int size)
78 {
79 APIRET rc = 0;
80 ULONG actual = 0;
81
82 for(ULONG current = 0; current < size; current += actual)
83 {
84 actual = 0;
85 CHECKIO("DosRead");
86
87 #ifdef DEBUG_LOCAL_CONNECTION
88 cout << MYTID << ": Reading: " << (ULONG)(size - current) << " @ "
89 << current << " of " << size << endl;
90 #endif
91
92 rc = DosRead(fPipeHandle, (PVOID)((char *)buffer + current),
93 (ULONG)(size - current), &actual);
94
95 #ifdef DEBUG_LOCAL_CONNECTION
96 cout << MYTID << ": Read : " << actual << " @ " << current
97 << " of " << size << " RC: " << rc << endl;
98 #endif
99
100 if ((actual == 0) && (size != 0))
101 {
102 STAFConnectionIOException noData("No data available on pipe");
103 THROW_STAF_EXCEPTION(noData);
104 }
105 }
106
107 #ifdef DEBUG_LOCAL_CONNECTION
108 if (size == 4) cout << MYTID << ": RNum : " << *((unsigned int *)buffer)
109 << endl;
110 else if (size) cout << MYTID << ": RData : "
111 << IString((char *)buffer, size) << endl;
112 else cout << MYTID << ": RZero" << endl;
113 #endif
114 }
115
116
write(void * buffer,unsigned int size)117 void STAFLocalConnection::write(void *buffer, unsigned int size)
118 {
119 APIRET rc = 0;
120 ULONG actual = 0;
121
122 for(ULONG current = 0; current < size; current += actual)
123 {
124 actual = 0;
125 #ifdef DEBUG_LOCAL_CONNECTION
126 cout << MYTID << ": Writing: " << (ULONG)(size - current) << " @ "
127 << current << " of " << size << endl;
128 #endif
129
130 rc = DosWrite(fPipeHandle, (PVOID)((char *)buffer + current),
131 (ULONG)(size - current), &actual);
132
133 #ifdef DEBUG_LOCAL_CONNECTION
134 cout << MYTID << ": Wrote : " << actual << " @ " << current
135 << " of " << size << " RC: " << rc << endl;
136 #endif
137
138 CHECKIO("DosWrite");
139
140 rc = DosResetBuffer(fPipeHandle);
141
142 // This if statement is here due to a bug (?) in Warp V3, where
143 // DosResetBuffer returns ERROR_BROKEN_PIPE or ERROR_PIPE_NOT_CONNECTED
144 // when the other side of the pipe has read the data and closed its end
145 // of the pipe. Warp V4 does not seem to exhibit this problem.
146 //
147 // This check should be fairly harmless, as, if this is the last
148 // write then it doesn't matter if the pipe is now broken. If
149 // it isn't the last write then the error will be returned on
150 // the next call, due to a failure on the DosWrite call.
151
152 if ((rc != ERROR_BROKEN_PIPE) && (rc != ERROR_PIPE_NOT_CONNECTED))
153 {
154 CHECKIO("DosResetBuffer");
155 }
156 }
157
158 #ifdef DEBUG_LOCAL_CONNECTION
159 if (size == 4) cout << MYTID << ": WNum : " << *((unsigned int *)buffer)
160 << " RC: " << rc << endl;
161 else if (size) cout << MYTID << ": WData : "
162 << IString((char *)buffer, size) << " RC: " << rc
163 << endl;
164 else cout << MYTID << ": WZero RC: " << rc << endl;
165 #endif
166 }
167
168
freeLocalConnection(STAFConnection * pConn)169 void STAFLocalConnection::freeLocalConnection(STAFConnection *pConn)
170 {
171 delete pConn;
172 }
173
174
~STAFLocalConnection()175 STAFLocalConnection::~STAFLocalConnection()
176 {
177 if (connectionMode() == kServer)
178 DosDisConnectNPipe(fPipeHandle);
179
180 DosClose(fPipeHandle);
181 }
182