Merge lp:~ralph-lange/epics-base/ca-over-tcp into lp:~epics-core/epics-base/3.14

Proposed by Ralph Lange
Status: Merged
Merged at revision: 12092
Proposed branch: lp:~ralph-lange/epics-base/ca-over-tcp
Merge into: lp:~epics-core/epics-base/3.14
Diff against target: 3727 lines (+1333/-650)
23 files modified
src/ca/CASG.cpp (+8/-12)
src/ca/CAref.html (+168/-155)
src/ca/SearchDest.h (+39/-0)
src/ca/caProto.h (+4/-1)
src/ca/ca_client_context.cpp (+8/-7)
src/ca/cac.cpp (+126/-60)
src/ca/cac.h (+34/-18)
src/ca/iocinf.cpp (+8/-7)
src/ca/nciu.h (+1/-1)
src/ca/tcpiiu.cpp (+128/-40)
src/ca/udpiiu.cpp (+213/-85)
src/ca/udpiiu.h (+37/-10)
src/ca/virtualCircuit.h (+48/-13)
src/cas/generic/caHdrLargeArray.h (+1/-1)
src/cas/generic/casStrmClient.cc (+256/-41)
src/cas/generic/casStrmClient.h (+77/-71)
src/cas/io/bsdSocket/casIntfIO.cc (+33/-34)
src/cas/io/bsdSocket/casStreamIO.cc (+20/-25)
src/cas/io/bsdSocket/casStreamIO.h (+24/-32)
src/libCom/env/envDefs.h (+1/-0)
src/rsrv/camessage.c (+74/-15)
src/rsrv/caservertask.c (+14/-10)
src/rsrv/server.h (+11/-12)
To merge this branch: bzr merge lp:~ralph-lange/epics-base/ca-over-tcp
Reviewer Review Type Date Requested Status
Andrew Johnson Approve
Jeff Hill Approve
Review via email: mp+23505@code.launchpad.net

Description of the change

Feature: Run CA over TCP only, so that it can be used through a single TCP tunnel (e.g. an SSH tunnel).

At the Codeathon 2008, Jeff and I were adding the necessary features to the CVS trunk (aka 3.15).

I pulled the changes into a feature branch against 3.14/trunk, so that they can be reviewed and (hopefully) merged into 3.14 soon - Andrew was suggesting this to be a topic at the Codeathon 2010.

I also did some more testing, finding and fixing two issues (bugs) in the 2008 changes.

To post a comment you must log in.
Revision history for this message
Jeff Hill (johill-lanl) wrote :

Looks fine, but its hard to catch everything with a source code review so testing is important. IMHO its important to keep bug fix changes and new features in different release series, and we seem to be slipping a bit on that level of discipline.

udpiiu.cpp comment on line 278 prob no-longer applies and can be removed

review: Approve
Revision history for this message
Ralph Lange (ralph-lange) wrote :

Thanks, Jeff.

I did some testing with a setup of two soft IOCs and the example name
server (that's actually how I found the two issues that were not working
in the 2008 Codeathon version), focussing on how the new feature behaves
in different situations ( IOCs and/or name servers going away and coming
back). I was also running the integration tests all ways (old client -
new server, new client - old server, new client - new server) to make
sure it did't obviously break existing behavior. Admittedly I did not
add any new tests to the test suite, as I found it hard to think of a
reasonable test. Do you have an idea?

If your IMHO remark refers to the bug fixes in the reference manual:
first I was reluctant, but then decided as these were fixing bugs in the
documentation only, it was not worth creating a new branch for that.

If you refer to adding a new feature to the 3.14 series: as I told you,
Andrew wants to discuss at the Codeathon which release this branch
should be merged to. Note that to escape the large number of meaningless
"sync" commit comments in the main CVS trunk, we decided a few months
ago that 3.15 should be developed from forking off the existing 3.14
branch (that has meaningful commit messages). To make this possible,
3.15 only changes in the CVS trunk have to be pulled out into
feature-branches against the 3.14 release - which is exactly what I was
doing with the "ca-over-tcp" feature. Now we can decide if that branch
should be part of 3.14 (before the split) or 3.15 (after the split).

I removed the comment in udpiiu.cpp as you suggested and pushed the
change onto LP.

Cheers,
Ralph

On Fri 14 May 2010 1:34:29 Jeff Hill wrote:
> Review: Approve
>
> Looks fine, but its hard to catch everything with a source code review so testing is important. IMHO its important to keep bug fix changes and new features in different release series, and we seem to be slipping a bit on that level of discipline.
>
> udpiiu.cpp comment on line 278 prob no-longer applies and can be removed
>

12053. By Ralph Lange <rlange@nsls2rlange>

Removed comment about ellfree @Windows in udpiiu.cpp (suggested by Jeff).

Revision history for this message
Jeff Hill (johill-lanl) wrote :
Download full text (3.4 KiB)

Hi Ralph,

Sorry about the "sync" commits on the main trunk. Certainly this is in retrospect a bit lazy on my part and I will need to be better in the future. However in my defense, the vast majority of the "sync" commits were for new code - the new server and the atomic primitives in libCom. The vast majority of the rest of them were related to epics mutex name space changes in src/ca.

I was writing code quickly and using the SCC system to transfer back and forth from my home to my workplace. For that type of development when the commit is occurring only to transfer the code between my house and my workplace the minutia comments are less beneficial (it can be hard to come up with insightful comments when you are tired, and leaving late). Note that this was work on new features and not patches. We definitely need the SCC comments for tracking patches. I do see that doing such developments on branches works better. I anticipate that the merge is going to take some extra work however.

The changes to the reference manual are fine. My concern is about maintaining quality in the production system, and from my perspective that can only be achieved if we make major releases on a slower schedule and then keep patching them until they are nearly perfect. My concern is that adding features to a patch series introduces quality control risk.

Thanks,

Jeff

> Thanks, Jeff.
>
> I did some testing with a setup of two soft IOCs and the example name
> server (that's actually how I found the two issues that were not working
> in the 2008 Codeathon version), focussing on how the new feature behaves
> in different situations ( IOCs and/or name servers going away and coming
> back). I was also running the integration tests all ways (old client -
> new server, new client - old server, new client - new server) to make
> sure it did't obviously break existing behavior. Admittedly I did not
> add any new tests to the test suite, as I found it hard to think of a
> reasonable test. Do you have an idea?
>
> If your IMHO remark refers to the bug fixes in the reference manual:
> first I was reluctant, but then decided as these were fixing bugs in the
> documentation only, it was not worth creating a new branch for that.
>
> If you refer to adding a new feature to the 3.14 series: as I told you,
> Andrew wants to discuss at the Codeathon which release this branch
> should be merged to. Note that to escape the large number of meaningless
> "sync" commit comments in the main CVS trunk, we decided a few months
> ago that 3.15 should be developed from forking off the existing 3.14
> branch (that has meaningful commit messages). To make this possible,
> 3.15 only changes in the CVS trunk have to be pulled out into
> feature-branches against the 3.14 release - which is exactly what I was
> doing with the "ca-over-tcp" feature. Now we can decide if that branch
> should be part of 3.14 (before the split) or 3.15 (after the split).
>
> I removed the comment in udpiiu.cpp as you suggested and pushed the
> change onto LP.
>
> Cheers,
> Ralph
>
>
> On Fri 14 May 2010 1:34:29 Jeff Hill wrote:
> > Review: Approve
> >
> > Looks fine, but its hard to catch everything with a sou...

Read more...

Revision history for this message
Andrew Johnson (anj) wrote :
Download full text (3.3 KiB)

Hi Ralph,

I started trying to merge branch this today. I added a default value ("") for EPICS_CA_NAME_SERVERS to configure/CONFIG_ENV to remove build warnings.

I'm getting a compile errors from my vxWorks builds, both 5.5.2 and 6.8. VxWorks 5.5.2 complains about line 613 in cac.cpp:

    bool newIIU = findOrCreateVirtCircuit (
        guard, addr,
        pChan->getPriority(guard), piiu, minorVersionNumber, false );

The last argument 'false' should be deleted as the prototype expects a pointer that defaults to 0. I don't know why the other arch's don't object to this, I guess they manage to convert the false into a NULL pointer.

5.5.2 also complains about udpiiu.cpp:

../udpiiu.cpp: In method `void udpiiu::SearchDestUDP::searchRequest(epicsGuard<epicsMutex> &, const char *, unsigned int)':
../udpiiu.h:153: `class epicsMutex & udpiiu::cacMutex' is private
../udpiiu.cpp:919: within this context
../udpiiu.h:160: `SOCKET udpiiu::sock' is private
../udpiiu.cpp:923: within this context
../udpiiu.h:164: `bool udpiiu::shutdownCmd' is private
../udpiiu.cpp:936: within this context
../udpiiu.cpp: In method `void udpiiu::SearchDestUDP::show(epicsGuard<epicsMutex> &, unsigned int) const':
../udpiiu.h:153: `class epicsMutex & udpiiu::cacMutex' is private
../udpiiu.cpp:970: within this context
../udpiiu.cpp: In method `void udpiiu::SearchRespCallback::notify(const caHdr &, const void *, const osiSockAddr &, const epicsTime &)':
../udpiiu.h:162: `ca_uint16_t udpiiu::serverPort' is private
../udpiiu.cpp:1033: within this context
../udpiiu.h:151: `class cac & udpiiu::cacRef' is private
../udpiiu.cpp:1038: within this context
../udpiiu.h:151: `class cac & udpiiu::cacRef' is private
../udpiiu.cpp:1043: within this context
../udpiiu.cpp: In method `void udpiiu::SearchRespCallback::show(epicsGuard<epicsMutex> &, unsigned int) const':
../udpiiu.h:153: `class epicsMutex & udpiiu::cacMutex' is private
../udpiiu.cpp:1052: within this context

It isn't giving member functions of nested classes access to their parent class private data members, which I can fix by adding a couple of friend definitions to class udpiiu in udpiiu.h:
    friend class udpiiu::SearchDestUDP;
    friend class udpiiu::SearchRespCallback;
With that change, vxWorks 5.5.2 builds OK.

VxWorks 6.8 also complains about udpiiu.cpp:

../udpiiu.cpp: In member function 'virtual void udpiiu::SearchDestUDP::searchRequest(epicsGuard<epicsMutex>&, const char*, size_t)':
../udpiiu.cpp:924: error: invalid conversion from 'const char*' to 'char*'
../udpiiu.cpp:924: error: initializing argument 2 of 'int sendto(int, char*, int, int, sockaddr*, int)'

The relevant code is:

void udpiiu :: SearchDestUDP :: searchRequest (
            epicsGuard < epicsMutex > & guard, const char * pBuf, size_t bufSize )
{
...
        int status = sendto ( _udpiiu.sock, pBuf, bufSizeAsInt, 0,
                & _destAddr.sa, sizeof ( _destAddr.sa ) );

In vxWorks the second argument to sendto() is not marked as const. Adding a const_cast<char *> around the argument is ugly, but the alternative was requiring changes to too many other files for me to finish exploring it. With that change vxWorks 6.8 finished building OK...

Read more...

review: Needs Fixing
Revision history for this message
Ralph Lange (ralph-lange) wrote :

Hi Andrew,

these fixes sound fine to me - please go ahead and commit them.

I'm especially sorry about the boolean vs. pointer issue - iirc that was one of my latest prototype changes that I obviously did not apply to all usages.

My test setup was running two standard (base) soft IOCs and the example name server. After starting a camonitor client connecting to one of the IOCs by UDP (through CA_ADDR_LIST) and the other IOC through the name server, you can check the behavior when IOCs and/or name server go down and come back for different combinations of the env variable settings.

Jeff is probably the only one who built this on Windows.

Thanks a lot!
Ralph

Revision history for this message
Andrew Johnson (anj) wrote :

Fixed.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/ca/CASG.cpp'
2--- src/ca/CASG.cpp 2007-08-23 17:46:28 +0000
3+++ src/ca/CASG.cpp 2010-05-14 13:38:34 +0000
4@@ -1,16 +1,15 @@
5 /*************************************************************************\
6-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
7-* National Laboratory.
8-* Copyright (c) 2002 The Regents of the University of California, as
9-* Operator of Los Alamos National Laboratory.
10-* EPICS BASE Versions 3.13.7
11-* and higher are distributed subject to a Software License Agreement found
12-* in file LICENSE that is included with this distribution.
13+ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
14+ * National Laboratory.
15+ * Copyright (c) 2002 The Regents of the University of California, as
16+ * Operator of Los Alamos National Laboratory.
17+ * EPICS BASE Versions 3.13.7
18+ * and higher are distributed subject to a Software License Agreement found
19+ * in file LICENSE that is included with this distribution.
20 \*************************************************************************/
21+
22 /*
23 * Author: Jeffrey O. Hill
24- * hill@luke.lanl.gov
25- * (505) 665 1831
26 */
27
28 #include <string>
29@@ -314,6 +313,3 @@
30 errlogPrintf ( "%s:%d this compiler is confused about placement delete - memory was probably leaked",
31 __FILE__, __LINE__ );
32 }
33-
34-
35-
36
37=== modified file 'src/ca/CAref.html'
38--- src/ca/CAref.html 2009-12-15 22:42:57 +0000
39+++ src/ca/CAref.html 2010-05-14 13:38:34 +0000
40@@ -19,25 +19,25 @@
41
42 <h1>EPICS R3.14 Channel Access Reference Manual</h1>
43 <address>
44- Jeffrey O. Hill
45+ Jeffrey O. Hill
46 </address>
47
48 <p><span style="font-size: x-small; font-weight:lighter;">Los Alamos National
49 Laboratory, SNS Division</span></p>
50 <address>
51- Ralph Lange
52+ Ralph Lange
53 </address>
54
55 <p><span style="font-size: x-small; font-weight:lighter;">Helmholtz-Zentrum
56 Berlin (BESSY II)</span></p>
57
58-<p><span style="font-size: xx-small; font-weight:lighter;">Copyright © 2009
59-Helmholtz-Zentrum Berlin für Materialien und Energie GmbH.<br>
60-Copyright © 2002 The University of Chicago, as Operator of Argonne National
61+<p><span style="font-size: xx-small; font-weight:lighter;">Copyright &copy; 2009
62+Helmholtz-Zentrum Berlin f&uuml;r Materialien und Energie GmbH.<br>
63+Copyright &copy; 2002 The University of Chicago, as Operator of Argonne National
64 Laboratory.<br>
65-Copyright © 2002 The Regents of the University of California, as Operator of
66+Copyright &copy; 2002 The Regents of the University of California, as Operator of
67 Los Alamos National Laboratory.<br>
68-Copyright © 2002 Berliner Speicherringgesellschaft für Synchrotronstrahlung
69+Copyright &copy; 2002 Berliner Speicherringgesellschaft f&uuml;r Synchrotronstrahlung
70 GmbH.</span></p>
71
72 <p><span style="font-size: xx-small; font-weight:lighter;">EPICS BASE Versions
73@@ -105,7 +105,7 @@
74
75 <h3><a href="#Troublesho">Troubleshooting</a></h3>
76 <ul>
77- <li><a href="#When">When Clients Do Not Connect to Their Server</a>
78+ <li><a href="#When">When Clients Do Not Connect to Their Server</a>
79 <ul>
80 <li><a href="#Broadcast">Client and Server Broadcast Addresses Dont
81 Match</a></li>
82@@ -136,7 +136,7 @@
83 <li><a href="#Connection">Connection Management</a></li>
84 <li><a href="#Thread">Thread Safety and Preemptive Callback to User
85 Code</a></li>
86- <li><a href="#Client2">CA Client Contexts and Application Specific Auxillary
87+ <li><a href="#Client2">CA Client Contexts and Application Specific Auxiliary
88 Threads</a></li>
89 <li><a href="#Polling">Polling the CA Client Library From Single Threaded
90 Applications</a></li>
91@@ -148,7 +148,7 @@
92 handlers</a></li>
93 </ul>
94
95-<h3>Functionality Index </h3>
96+<h3>Functionality Index</h3>
97 <ul>
98 <li><a href="#ca_context_create">create CA client context</a></li>
99 <li><a href="#ca_context_destroy">terminate CA client context</a></li>
100@@ -158,7 +158,7 @@
101 <li><a href="#ca_put">write to a channel and wait for initiated activities to
102 complete</a></li>
103 <li><a href="#ca_get">read from a channel</a></li>
104- <li><a href="#ca_add_event">subscribe for state change updates</a></li>
105+ <li><a href="#ca_add_event">subscribe for state change updates</a></li>
106 <li><a href="#ca_clear_event">cancel a subscription</a></li>
107 <li><a href="#ca_pend_io">block for certain requests to complete</a></li>
108 <li><a href="#ca_test_io">test to see if certain requests have
109@@ -178,13 +178,13 @@
110 <li><a href="#ca_get">ca_array_get_callback</a></li>
111 <li><a href="#ca_put">ca_array_put</a></li>
112 <li><a href="#ca_put">ca_array_put_callback</a></li>
113- <li><a href="#ca_attach_context">ca_attach_context </a></li>
114+ <li><a href="#ca_attach_context">ca_attach_context</a></li>
115 <li><a href="#ca_clear_channel">ca_clear_channel</a></li>
116 <li><a href="#ca_clear_event">ca_clear_subscription</a></li>
117 <li><a href="#ca_client_status">ca_client_status</a></li>
118 <li><a href="#ca_context_create">ca_context_create</a></li>
119 <li><a href="#ca_context_destroy">ca_context_destroy</a></li>
120- <li><a href="CAref.html#ca_client_status">ca_context_status</a></li>
121+ <li><a href="#ca_client_status">ca_context_status</a></li>
122 <li><a href="#ca_create_channel">ca_create_channel</a></li>
123 <li><a href="#ca_add_event">ca_create_subscription</a></li>
124 <li><a href="#ca_current_context">ca_current_context</a></li>
125@@ -283,6 +283,11 @@
126 <td>YES</td>
127 </tr>
128 <tr>
129+ <td>EPICS_CA_NAME_SERVERS</td>
130+ <td>{N.N.N.N N.N.N.N:P ...}</td>
131+ <td>&lt;none&gt;</td>
132+ </tr>
133+ <tr>
134 <td>EPICS_CA_CONN_TMO</td>
135 <td>r &gt; 0.1 seconds</td>
136 <td>30.0</td>
137@@ -299,7 +304,7 @@
138 </tr>
139 <tr>
140 <td>EPICS_CA_SERVER_PORT</td>
141- <td>i &gt; 5000</td>
142+ <td>i &gt; 5000</td>
143 <td>5064</td>
144 </tr>
145 <tr>
146@@ -327,7 +332,7 @@
147 <tbody>
148 <tr>
149 <td>C shell</td>
150- <td>setenv EPICS_CA_ADDR_LIST  1.2.3.4</td>
151+ <td>setenv EPICS_CA_ADDR_LIST 1.2.3.4</td>
152 </tr>
153 <tr>
154 <td>bash</td>
155@@ -335,7 +340,7 @@
156 </tr>
157 <tr>
158 <td>vxWorks shell</td>
159- <td>putenv ( "EPICS_CA_ADDR_LIST =1.2.3.4" )</td>
160+ <td>putenv ( "EPICS_CA_ADDR_LIST=1.2.3.4" )</td>
161 </tr>
162 <tr>
163 <td>DOS command line</td>
164@@ -352,7 +357,7 @@
165
166 <p>Normally in a local area network (LAN) environment CA discovers the address
167 of the host for an EPICS process variable by broadcasting frames containing a
168-list of channel names ( CA search messages ) and waiting for responses from the
169+list of channel names (CA search messages) and waiting for responses from the
170 servers that host the channels identified. Likewise CA clients efficiently
171 discover that CA servers have recently joined the LAN or disconnected from the
172 LAN by monitoring periodically broadcasted beacons sent out by the servers.
173@@ -362,7 +367,7 @@
174
175 <h3><a name="Network">IP Network Administration Background Information</a></h3>
176
177-<p>Channel Access is implemented using internet protocols (IP). IP addresses
178+<p>Channel Access is implemented using internet protocols (IP). IP addresses
179 are divided into host and network portions. The boundary between each portion
180 is determined by the IP netmask. Portions of the IP address corresponding to
181 zeros in the netmask specify the hosts address within an IP subnet. Portions of
182@@ -415,7 +420,7 @@
183 site might set up an operational control system and a test control system on
184 the same network. In this situation it is desirable for the test system and the
185 operational system to use identical PV names without fear of collision. A site
186-might also configure the CA port numbers because some other facility is already
187+might also configure the CA port numbers because some other facility is already
188 using the default port numbers. The default Channel Access port numbers have
189 been registered with IANA.</p>
190
191@@ -464,23 +469,31 @@
192 broadcast address of that subnet is added to the list. For each point to point
193 interface found, the destination address of that link is added to the list.
194 This automatic server address list initialization can be disabled if the EPICS
195-environment variable "EPICS_CA_AUTO_ADDR_LIST" exists and its value is either
196+environment variable EPICS_CA_AUTO_ADDR_LIST exists and its value is either
197 of "no" or "NO". The typical default is to enable network interface
198-introspection driven initialization with "EPICS_CA_AUTO_ADDR_LIST" set to "YES"
199+introspection driven initialization with EPICS_CA_AUTO_ADDR_LIST set to "YES"
200 or "yes".</p>
201
202 <p>Following network interface introspection, any IP addresses specified in the
203 EPICS environment variable EPICS_CA_ADDR_LIST are added to the list of
204 destination addresses for CA client name resolution requests. In an EPICS
205 system crossing multiple subnets the EPICS_CA_ADDR_LIST must be set so that CA
206-name resolution ( search requests ) frames pass from CA clients to the targeted
207+name resolution (search requests) frames pass from CA clients to the targeted
208 CA servers unless a CA proxy (gateway) is installed. The addresses in
209 EPICS_CA_ADDR_LIST may be dotted IP addresses or host names if the local OS has
210 support for host name to IP address translation. When multiple names are added
211 to EPICS_CA_ADDR_LIST they must be separated by white space. There is no
212-requirement that the addresses specified in the EPICS_CA_ADDR_LIST be a
213+requirement that the addresses specified in the EPICS_CA_ADDR_LIST be
214 broadcast addresses, but this will often be the most convenient choice.</p>
215
216+<p>For any IP addresses specified in the EPICS environment variable
217+EPICS_CA_NAME_SERVERS, TCP connections are opened and used for CA client name
218+resolution requests. (Thus, broadcast addresses are not allowed in
219+EPICS_CA_NAME_SERVERS.) When used in combination with an empty
220+EPICS_CA_ADDR_LIST and EPICS_CA_AUTO_ADDR_LIST set to "NO", Channel Access can
221+be run without using UDP for name resolution. Such an TCP-only mode allows for
222+Channel Access to work e.g. through SSH tunnels.</p>
223+
224 <table border="1">
225 <tbody>
226 <tr>
227@@ -716,7 +729,7 @@
228 EPICS_CA_MAX_ARRAY_BYTES determines the size of the largest array that may pass
229 through CA. Prior to this version only arrays smaller than 16k bytes could be
230 transfered. The CA libraries maintains a free list of 16384 byte network
231-buffers that are used for ordinary communication. If EPICS_CA_MAX_ARRAY_BYTES 
232+buffers that are used for ordinary communication. If EPICS_CA_MAX_ARRAY_BYTES
233 is larger than 16384 then a second free list of larger data buffers is
234 established and used only after a client send its first large array request.</p>
235
236@@ -751,7 +764,7 @@
237 </tr>
238 <tr>
239 <td>EPICS_CAS_SERVER_PORT</td>
240- <td>i &gt; 5000</td>
241+ <td>i &gt; 5000</td>
242 <td>EPICS_CA_SERVER_PORT</td>
243 </tr>
244 <tr>
245@@ -766,12 +779,12 @@
246 </tr>
247 <tr>
248 <td>EPICS_CAS_BEACON_PERIOD</td>
249- <td>r &gt; 0.1 seconds</td>
250+ <td>r &gt; 0.1 seconds</td>
251 <td>EPICS_CA_BEACON_PERIOD</td>
252 </tr>
253 <tr>
254 <td>EPICS_CAS_BEACON_PORT</td>
255- <td>i &gt; 5000</td>
256+ <td>i &gt; 5000</td>
257 <td>EPICS_CA_REPEATER_PORT</td>
258 </tr>
259 <tr>
260@@ -824,8 +837,8 @@
261 list is not augmented.</p>
262
263 <p>The EPICS_CAS_BEACON_PORT parameter specifies the destination port for
264-server beacons. The only exception to this occurs when ports are specified in
265-EPICS_CAS_BEACON_ADDR_LIST or possibly in EPICS_CA_ADDR_LIST. If
266+server beacons. The only exception to this occurs when ports are specified
267+in EPICS_CAS_BEACON_ADDR_LIST or possibly in EPICS_CA_ADDR_LIST. If
268 EPICS_CAS_BEACON_PORT is not specified then beacons are sent to the port
269 specified in EPICS_CA_REPEATER_PORT.</p>
270
271@@ -846,7 +859,7 @@
272
273 <p>Name resolution requests originating from any of the IP addresses specified
274 in the EPICS_CAS_IGNORE_ADDR_LIST parameter are not replied to.<em>In R3.14 and
275-previous releases the CA server employed by iocCore does not implemet this
276+previous releases the CA server employed by iocCore does not implement this
277 feature.</em></p>
278
279 <h4>Client Configuration that also Applies to Servers</h4>
280@@ -1082,11 +1095,11 @@
281 </tr>
282 <tr>
283 <td>-w &lt;sec&gt;</td>
284- <td>Wait time, specifies CA timeout, default is 1.0 second(s)</td>
285+ <td>Wait time, specifies longer CA timeout, default is 1.0 second</td>
286 </tr>
287 <tr>
288 <td>-c</td>
289- <td>Asynchronous get (use ca_get_callback and wait for completion)</td>
290+ <td>Asynchronous get (use ca_get_callback instead of ca_get)</td>
291 </tr>
292 <tr>
293 <td>-p &lt;prio&gt;</td>
294@@ -1115,7 +1128,7 @@
295 </tr>
296 <tr>
297 <td>-d &lt;type&gt;</td>
298- <td>Request specific dbr type; use string (DBR_ prefix may be omitted)
299+ <td>Request specific dbr type; use string (DBR_ prefix may be omitted)
300
301 <p>or number of one of the following types:</p>
302
303@@ -1341,7 +1354,7 @@
304 </tr>
305 <tr>
306 <td>-w &lt;sec&gt;</td>
307- <td>Wait time, specifies CA timeout, default is 1.0 second(s)</td>
308+ <td>Wait time, specifies longer CA timeout, default is 1.0 second</td>
309 </tr>
310 <tr>
311 <td>-m &lt;mask&gt;</td>
312@@ -1495,7 +1508,7 @@
313 </tr>
314 <tr>
315 <td>-w &lt;sec&gt;</td>
316- <td>Wait time, specifies CA timeout, default is 1.0 second(s)</td>
317+ <td>Wait time, specifies longer CA timeout, default is 1.0 second</td>
318 </tr>
319 <tr>
320 <td>-c</td>
321@@ -1583,7 +1596,7 @@
322 </tr>
323 <tr>
324 <td>-w &lt;sec&gt;</td>
325- <td>Wait time, specifies CA timeout, default is 1.0 second(s)</td>
326+ <td>Wait time, specifies longer CA timeout, default is 1.0 second</td>
327 </tr>
328 <tr>
329 <td>-s &lt;level&gt;</td>
330@@ -1973,8 +1986,8 @@
331 <p>If the subscription update producer in the server produces subscription
332 updates faster than the subscription update consumer in the client consumes
333 them, then events have to be discarded if the buffering in the server
334-isn&rsquo;t allowed to grow to an infinite size. This is a law of nature
335-&ndash; based on queuing theory of course.</p>
336+isn't allowed to grow to an infinite size. This is a law of nature
337+- based on queuing theory of course.</p>
338
339 <p>What is done depends on the version of the CA server. All server versions
340 place quotas on the maximum number of subscription updates allowed on the
341@@ -1996,10 +2009,10 @@
342 getting time warped, but also guarantees that intervening events are discarded
343 until the slow client catches up.</p>
344
345-<p>There is currently no message on the IOC&rsquo;s console when a particular
346-client is slow on the uptake. A message of this type used to exist many years
347-ago, but it was a source of confusion (and what we will call message noise) so
348-it was removed. </p>
349+<p>There is currently no message on the IOC's console when a
350+particular client is slow on the uptake. A message of this type used to exist
351+many years ago, but it was a source of confusion (and what we will call
352+message noise) so it was removed. </p>
353
354 <p>There is unfortunately no field in the protocol allowing the server to
355 indicate that an intervening subscription update was discarded. We should
356@@ -2212,7 +2225,7 @@
357 #include "cadef.h"
358
359 int main ( int argc, char ** argv )
360-{
361+{
362 struct dbr_time_double * pTD;
363 const dbr_double_t * pValue;
364 unsigned nBytes;
365@@ -2222,12 +2235,12 @@
366 chid chan;
367 double sum;
368 int status;
369-
370+
371 if ( argc != 2 ) {
372 fprintf ( stderr, "usage: %s &lt;channel name&gt;", argv[0] );
373 return -1;
374 }
375-
376+
377 status = ca_create_channel ( argv[1], 0, 0, 0, &amp; chan );
378 SEVCHK ( status, "ca_create_channel()" );
379 status = ca_pend_io ( 15.0 );
380@@ -2243,7 +2256,7 @@
381 fprintf ( stderr, "insufficient memory to complete request\n" );
382 return -1;
383 }
384-
385+
386 status = ca_array_get ( DBR_TIME_DOUBLE, elementCount, chan, pTD );
387 SEVCHK ( status, "ca_array_get()" );
388 status = ca_pend_io ( 15.0 );
389@@ -2251,23 +2264,23 @@
390 fprintf ( stderr, "\"%s\" didnt return a value.\n", argv[1] );
391 return -1;
392 }
393-
394- pValue = &amp; pTD-&gt;value;
395- sum = 0.0;
396- for ( i = 0; i &lt; elementCount; i++ ) {
397- sum += pValue[i];
398+
399+ pValue = &amp; pTD-&gt;value;
400+ sum = 0.0;
401+ for ( i = 0; i &lt; elementCount; i++ ) {
402+ sum += pValue[i];
403 }
404-
405+
406 epicsTimeToStrftime ( timeString, sizeof ( timeString ),
407 "%a %b %d %Y %H:%M:%S.%f", &amp; pTD-&gt;stamp );
408
409 printf ( "The sum of elements in %s at %s was %f\n",
410 argv[1], timeString, sum );
411-
412+
413 ca_clear_channel ( chan );
414 ca_task_exit ();
415 free ( pTD );
416-
417+
418 return 0;
419 }</code></pre>
420
421@@ -2310,7 +2323,7 @@
422 <h3><a name="Channel1">Channel Access Exceptions</a></h3>
423
424 <p>When the server detects a failure, and there is no client call back function
425-attached to the request, then an exception handler is executed in the client.
426+attached to the request, an exception handler is executed in the client.
427 The default exception handler prints a message on the console and exits if the
428 exception condition is severe. Certain internal exceptions within the CA client
429 library, and failures detected by the SEVCHK macro may also cause the exception
430@@ -2332,8 +2345,8 @@
431 <h3><a name="Arrays">Arrays</a></h3>
432
433 <p>For routines that require an argument specifying the number of array
434-elements, no more than the process variable's maximum native element count may
435-be requested. The process variable's maximum native element count is available
436+elements, no more than the process variable's maximum native element count may
437+be requested. The process variable's maximum native element count is available
438 from ca_element_count() when the channel is connected. If less elements than
439 the process variable's native element count are requested the requested values
440 will be fetched beginning at element zero. By default CA limits the number of
441@@ -2376,19 +2389,19 @@
442
443 <p>Starting with EPICS R3.14 the CA client libraries are fully thread safe on
444 all OS (in past releases the library was thread safe only on vxWorks). When the
445-client library is initialized the programmer may specify if preemptive call
446-back is enabled. Preemptive call back is disabled by default. If preemptive
447-call back is enabled then the user's call back functions might be called by
448+client library is initialized the programmer may specify if preemptive callback
449+is to be enabled. Preemptive callback is disabled by default. If preemptive
450+callback is enabled, then the user's callback functions might be called by
451 CA's auxiliary threads when the main initiating channel access thread is not
452 inside of a function in the channel access client library. Otherwise, the
453-user's call back functions will be called only when the main initiating channel
454+user's callback functions will be called only when the main initiating channel
455 access thread is executing inside of the CA client library. When the CA client
456-library invokes a user's call back function it will always wait for the current
457-callback to complete prior to executing another call back function. Programmers
458+library invokes a user's callback function, it will always wait for the current
459+callback to complete prior to executing another callback function. Programmers
460 enabling preemptive callback should be familiar with using mutex locks to
461 create a reliable multi-threaded program.</p>
462
463-<p>To set up a traditional single threaded client you will need code like this
464+<p>To set up a traditional single threaded client, you will need code like this
465 (see <a href="#ca_context_create">ca_context_create</a> and <a
466 href="#Client2">CA Client Contexts and Application Specific Auxiliary
467 Threads</a>) .</p>
468@@ -2412,7 +2425,7 @@
469 database CA links and the sequencer are designed to not use the same CA client
470 library threads, network circuits, and data structures. Each thread that calls
471 <a href="#ca_context_create">ca_context_create()</a> for the first time either
472-directly, or implicitly when calling any CA library function for the first
473+directly or implicitly when calling any CA library function for the first
474 time, creates a CA client library context. A CA client library context contains
475 all of the threads, network circuits, and data structures required to connect
476 and communicate with the channels that a CA client application has created. The
477@@ -2432,6 +2445,7 @@
478 with a CA context it need only make ordinary ca_xxxx() library calls to use the
479 context.</p>
480
481+
482 <p>A CA client library context can be shut down and cleaned up, after
483 destroying any channels or application specific threads that are attached to
484 it, by calling <a href="#ca_context_destroy">ca_context_destroy()</a>. The
485@@ -2484,9 +2498,9 @@
486 <ul>
487 <li>The vxWorks shell thread runs at the very highest priority in the system
488 and therefore socket calls are made at a priority that is above the
489- priority of tNetTask &minus; a practice that has caused the WRS IP kernel
490+ priority of tNetTask - a practice that has caused the WRS IP kernel
491 to get sick in the past. That symptom was observed some time ago, but we
492- don&rsquo;t know if WRS has fixed the problem.</li>
493+ don't know if WRS has fixed the problem.</li>
494 </ul>
495 <ul>
496 <li>The vxWorks shell thread runs at the very highest priority in the system
497@@ -2501,7 +2515,7 @@
498 <ul>
499 <li>In EPICS R3.13 the CA client library installed vxWorks task exit handlers
500 behaved strangely if CA functions were called from the vxWorks shell,
501- ca_task_exit() wasn&rsquo;t called, and the vxWorks shell restarted. In
502+ ca_task_exit() wasn't called, and the vxWorks shell restarted. In
503 EPICS R3.14 vxWorks task exit handlers are not installed and therefore
504 cleanup is solely the responsibility of the user. With EPICS R3.14 the user
505 must call ca_context_destroy or ca_task_exit to clean up on vxWorks. This
506@@ -2584,7 +2598,7 @@
507
508 <h4>Description</h4>
509
510-<p>Shut down the calling thread's channel access client context and free any
511+<p>Shut down the calling thread's channel access client context and free any
512 resources allocated. Detach the calling thread from any CA client context.</p>
513
514 <p>Any user-created threads that have attached themselves to the CA context
515@@ -2637,8 +2651,8 @@
516 on a channel.</p>
517
518 <p>The circuit may be initially connected or disconnected depending on the
519-state of the network and the location of the channel. A channel will only enter
520-a connected state after server's address is determined, and only if channel
521+state of the network and the location of the channel. A channel will only enter
522+a connected state after server's address is determined, and only if channel
523 access successfully establishes a virtual circuit through the network to the
524 server. Channel access routines that send a request to a server will return
525 ECA_DISCONNCHID if the channel is currently disconnected.</p>
526@@ -2676,7 +2690,7 @@
527 <dd>A nil terminated process variable name string. EPICS process control
528 function block database variable names are of the form "&lt;record
529 name&gt;.&lt;field name&gt;". If the field name and the period separator
530- are omitted then the "VAL" field is implicit. For example "RFHV01" and
531+ are omitted then the "VAL" field is implicit. For example "RFHV01" and
532 "RFHV01.VAL" reference the same EPICS process control function block
533 database variable.</dd>
534 </dl>
535@@ -2685,7 +2699,7 @@
536 <dd>Optional address of the user's call back function to be run when the
537 connection state changes. Casual users of channel access may decide to
538 set this field to nil or 0 if they do not need to have a call back
539- function run in response to each connection state change event.
540+ function run in response to each connection state change event.
541 <p>The following structure is passed <em>by value </em>to the user's
542 connection connection callback function. The <code>op</code> field will
543 be set by the CA client library to <code>CA_OP_CONN_UP</code> when the
544@@ -2701,8 +2715,8 @@
545 </dl>
546 <dl>
547 <dt><code>PUSER</code></dt>
548- <dd>The value of this void pointer argument is retained in
549- storage associated with the specified channel. See the MACROS manual page
550+ <dd>The value of this void pointer argument is retained in
551+ storage associated with the specified channel. See the MACROS manual page
552 for reading and writing this field. Casual users of channel access may
553 wish to set this field to nil or 0.</dd>
554 </dl>
555@@ -2743,7 +2757,7 @@
556
557 <h4>Description</h4>
558
559-<p>Shutdown and reclaim resources associated with a channel created by
560+<p>Shutdown and reclaim resources associated with a channel created by
561 ca_create_channel().</p>
562
563 <p>All remote operation requests such as the above are accumulated (buffered)
564@@ -2753,7 +2767,7 @@
565
566 <p>Clearing a channel does not cause its disconnect handler to be called, but
567 clearing a channel does shutdown and reclaim any channel state change event
568-subscriptions (monitors) registered with the channel.</p>
569+subscriptions (monitors) registered with the channel.</p>
570
571 <h4>Arguments</h4>
572 <dl>
573@@ -2787,13 +2801,13 @@
574
575 <p>Write a scalar or array value to a process variable.</p>
576
577-<p>When ca_array_put  or ca_put are invoked the client will receive no response
578+<p>When ca_array_put or ca_put are invoked the client will receive no response
579 unless the request can not be fulfilled in the server. If unsuccessful an
580-exception handler is run on the client side. </p>
581+exception handler is run on the client side.</p>
582
583 <p>When ca_array_put_callback are invoked the user supplied asynchronous call
584-back is called only after the initiated write operation, and all actions
585-resulting from the initiating write operation, complete.</p>
586+back is called only after the initiated write operation, and all actions
587+resulting from the initiating write operation, complete.</p>
588
589 <p>If unsuccessful the call back function is invoked indicating failure status.
590 </p>
591@@ -2802,7 +2816,7 @@
592 then the client's call back function is called with failure status, but this
593 does not guarantee that the server did not receive and process the request
594 before the disconnect. If a connection is lost and then resumed outstanding ca
595-put requests are not automatically reissued following reconnect.</p>
596+put requests are not automatically reissued following reconnect.</p>
597
598 <p>All of these functions return ECA_DISCONN if the channel is currently
599 disconnected.</p>
600@@ -2860,7 +2874,7 @@
601 </dl>
602 <dl>
603 <dt><code>PFUNC</code></dt>
604- <dd>address of <a href="#User">user supplied callback function</a> to be
605+ <dd>address of <a href="#User">user supplied callback function</a> to be
606 run when the requested operation completes</dd>
607 </dl>
608 <dl>
609@@ -2888,7 +2902,7 @@
610 <p>ECA_DISCONN - Channel is disconnected</p>
611
612 <h4>See Also</h4>
613-ca_flush_io()
614+ca_flush_io()
615
616 <p>ca_pend_event()</p>
617
618@@ -2915,12 +2929,13 @@
619 assumed to be stable in the application supplied buffer until after ECA_NORMAL
620 is returned from ca_pend_io. If a connection is lost outstanding ca get
621 requests are not automatically reissued following reconnect.</p>
622-When ca_get_callback or ca_array_get_callback are invoked a value is read
623-from the channel and then the user's callback is invoked with a pointer to the
624+
625+<p>When ca_get_callback or ca_array_get_callback are invoked a value is read
626+from the channel and then the user's callback is invoked with a pointer to the
627 retrieved value. Note that ca_pend_io will not block for the delivery of values
628 requested by ca_get_callback. If the channel disconnects before a ca get
629 callback request can be completed, then the clients call back function is
630-called with failure status.
631+called with failure status.</p>
632
633 <p>All of these functions return ECA_DISCONN if the channel is currently
634 disconnected.</p>
635@@ -2992,7 +3007,7 @@
636 <p>ECA_DISCONN - Channel is disconnected</p>
637
638 <h4>See Also</h4>
639-ca_pend_io()
640+ca_pend_io()
641
642 <p>ca_pend_event()</p>
643
644@@ -3010,7 +3025,7 @@
645 <h4>Description</h4>
646
647 <p>Register a state change subscription and specify a call back function to be
648-invoked whenever the process variable undergoes significant state changes. A
649+invoked whenever the process variable undergoes significant state changes. A
650 significant change can be a change in the process variable's value, alarm
651 status, or alarm severity. In the process control function block database the
652 deadband field determines the magnitude of a significant change for for the
653@@ -3018,7 +3033,7 @@
654 client library and potentially a CA server until one of ca_clear_channel or
655 ca_clear_event is called.</p>
656
657-<p>Subscriptions may be installed or canceled against both connected and
658+<p>Subscriptions may be installed or canceled against both connected and
659 disconnected channels. The specified USERFUNC is called once immediately after
660 the subscription is installed with the process variable's current state if the
661 process variable is connected. Otherwise, the specified USERFUNC is called
662@@ -3027,7 +3042,7 @@
663 variable's current state from within ca_add_event() if the client and the
664 process variable share the same address space.</p>
665
666-<p>If a subscription is installed on a channel in a disconnected state then the
667+<p>If a subscription is installed on a channel in a disconnected state then the
668 requested count will be set to the native maximum element count of the channel
669 if the requested count is larger.</p>
670
671@@ -3038,8 +3053,8 @@
672
673 <p>If at any time after subscribing, read access to the specified process
674 variable is lost, then the call back will be invoked immediately indicating
675-that read access was lost via the status argument. When read access is restored
676-normal event processing will resume starting always with at least one update
677+that read access was lost via the status argument. When read access is restored
678+normal event processing will resume starting always with at least one update
679 indicating the current state of the channel.</p>
680
681 <p>A better name for this function might have been ca_subscribe.</p>
682@@ -3066,7 +3081,7 @@
683 </dl>
684 <dl>
685 <dt><code>USRERFUNC</code></dt>
686- <dd>The address of <a href="#User">user supplied callback function</a> to
687+ <dd>The address of <a href="#User">user supplied callback function</a> to
688 be invoked with each subscription update.</dd>
689 </dl>
690 <dl>
691@@ -3082,7 +3097,7 @@
692 <dt><code>PEVID</code></dt>
693 <dd>This is a pointer to user supplied event id which is overwritten if
694 successful. This event id can later be used to clear a specific
695- event. This option may may be omitted by passing a nil pointer.</dd>
696+ event. This option may may be omitted by passing a nil pointer.</dd>
697 </dl>
698 <dl>
699 <dt><code>MASK</code></dt>
700@@ -3117,7 +3132,7 @@
701 <p>ECA_ADDFAIL - A local database event add failed</p>
702
703 <h4>See Also</h4>
704-ca_pend_event()
705+ca_pend_event()
706
707 <p>ca_flush_io()</p>
708
709@@ -3130,7 +3145,7 @@
710 <p>Cancel a subscription.</p>
711
712 <p>All ca_clear_event() requests such as the above are accumulated (buffered)
713-and not forwarded to the server until one of ca_flush_io, ca_pend_io,
714+and not forwarded to the server until one of ca_flush_io, ca_pend_io,
715 ca_pend_event, or ca_sg_pend are called. This allows several requests to be
716 efficiently sent together in one message.</p>
717
718@@ -3167,7 +3182,7 @@
719 </ul>
720
721 <p>If ECA_TIMEOUT is returned then get requests may be reissued followed by a
722-subsequent call to ca_pend_io(). Specifically, the function will block only for
723+subsequent call to ca_pend_io(). Specifically, the function will block only for
724 outstanding <a href="#ca_get">ca_get</a> requests issued, and also any channels
725 created specifying a nill connection handler function pointer, after the last
726 call to ca_pend_io() or ca client context creation whichever is later. Note
727@@ -3177,7 +3192,7 @@
728
729 <p>If no <a href="#ca_get">ca_get</a> or connection state change events are
730 outstanding then ca_pend_io() will flush the send buffer and return immediately
731-<em>without processing any outstanding channel access background
732+<em>without processing any outstanding channel access background
733 activities</em>.</p>
734
735 <p>The delay specified to ca_pend_io() should take into account worst case
736@@ -3192,7 +3207,7 @@
737 <dl>
738 <dt>TIMEOUT</dt>
739 <dd>Specifies the time out interval. A <code>TIMEOUT</code> interval of
740- zero specifies forever.</dd>
741+ zero specifies forever.</dd>
742 </dl>
743
744 <h4>Returns</h4>
745@@ -3205,7 +3220,7 @@
746 <p>ECA_EVDISALLOW - Function inappropriate for use within an event handler</p>
747
748 <h4>See Also</h4>
749-<a href="#ca_get">ca_get</a>()
750+<a href="#ca_get">ca_get</a>()
751
752 <p><a href="#ca_create_channel">ca_create_channel</a>()</p>
753
754@@ -3217,12 +3232,12 @@
755
756 <h4>Description</h4>
757
758-<p>This function tests to see if all <a href="#ca_get">ca_get</a> requests are
759+<p>This function tests to see if all <a href="#ca_get">ca_get</a> requests are
760 complete and channels created specifying a nill connection callback function
761 pointer are connected. It will report the status of outstanding <a
762 href="#ca_get">ca_get</a> requests issued, and channels created specifying a
763 nill connection callback function pointer, after the last call to ca_pend_io()
764-or CA context initialization whichever is later.</p>
765+or CA context initialization whichever is later.</p>
766
767 <h4>Returns</h4>
768
769@@ -3280,8 +3295,8 @@
770
771 <h4>Description</h4>
772
773-<p>Flush outstanding IO requests to the server. This routine might be useful
774-to users who need to flush requests prior to performing client side labor in
775+<p>Flush outstanding IO requests to the server. This routine might be useful
776+to users who need to flush requests prior to performing client side labor in
777 parallel with labor performed in the server.</p>
778
779 <p>Outstanding requests are also sent whenever the buffer which holds them
780@@ -3324,7 +3339,7 @@
781 </dl>
782 <dl>
783 <dt><code>CONTEXT_STRING</code></dt>
784- <dd>A null terminated character string to supply as error context to
785+ <dd>A null terminated character string to supply as error context to
786 diagnostics.</dd>
787 </dl>
788
789@@ -3345,9 +3360,9 @@
790
791 <p>When an error occurs in the server asynchronous to the clients thread then
792 information about this type of error is passed from the server to the client in
793-an exception message. When the client receives this exception message an
794+an exception message. When the client receives this exception message an
795 exception handler callback is called.The default exception handler prints a
796-diagnostic message on the client's standard out and terminates execution if the
797+diagnostic message on the client's standard out and terminates execution if the
798 error condition is severe.</p>
799
800 <p>Note that certain fields in "struct exception_handler_args" are not
801@@ -3364,7 +3379,7 @@
802 reinstalled. The following structure is passed by value to the user's
803 callback function. Currently, the <code>op </code>field can be one of
804 <code>CA_OP_GET, CA_OP_PUT, CA_OP_CREATE_CHANNEL, CA_OP_ADD_EVENT,
805- CA_OP_CLEAR_EVENT, or CA_OP_OTHER.</code>
806+ CA_OP_CLEAR_EVENT, or CA_OP_OTHER.</code>
807 <pre><code>struct exception_handler_args {
808 void *usr; /* user argument supplied when installed */
809 chanId chid; /* channel id (may be nill) */
810@@ -3387,23 +3402,22 @@
811
812 <h4>Example</h4>
813 <pre><code>void ca_exception_handler (
814- struct exception_handler_args args)
815+ struct exception_handler_args args)
816 {
817- char buf[512];
818- char *pName;
819+ char buf[512];
820+ char *pName;
821
822- if ( args.chid ) {
823- pName = ca_name ( args.chid );
824- }
825- else{
826- pName = "?";
827- }
828- sprintf ( buf,
829- "%s - with request chan=%s op=%d data type=%s count=%d",
830- args.ctx, pName, args.op, dbr_type_to_text ( args.type ), args.count );
831- ca_signal ( args.stat, buf );
832-
833-}
834+ if ( args.chid ) {
835+ pName = ca_name ( args.chid );
836+ }
837+ else {
838+ pName = "?";
839+ }
840+ sprintf ( buf,
841+ "%s - with request chan=%s op=%d data type=%s count=%d",
842+ args.ctx, pName, args.op, dbr_type_to_text ( args.type ), args.count );
843+ ca_signal ( args.stat, buf );
844+}
845 ca_add_exception_event ( ca_exception_handler , 0 );</code></pre>
846
847 <h4>Returns</h4>
848@@ -3419,7 +3433,7 @@
849 <h4>Description</h4>
850
851 <p>For use with the services provided by a file descriptor manager (IO
852-multiplexor) such as ""fdmgr.c". A file descriptor manager is often needed when
853+multiplexor) such as "fdmgr.c". A file descriptor manager is often needed when
854 two file descriptor IO intensive libraries such as the EPICS channel access
855 client library and the X window system client library must coexist in the same
856 UNIX process. This function allows an application code to be notified whenever
857@@ -3535,7 +3549,7 @@
858 <li>whenever the access rights state of a connected channel changes</li>
859 </ul>
860
861-<p>When a channel is created no access rights handler is installed.</p>
862+<p>When a channel is created no access rights handler is installed.</p>
863
864 <h4>Arguments</h4>
865 <dl>
866@@ -3587,7 +3601,7 @@
867 <h4>Returns</h4>
868 <dl>
869 <dt><code>TYPE</code></dt>
870- <dd>The data type code will be a member of the set of DBF_XXXX in
871+ <dd>The data type code will be a member of the set of DBF_XXXX in
872 db_access.h. The constant TYPENOTCONN is returned if the channel is
873 disconnected.<a name="ca_element_count"></a></dd>
874 </dl>
875@@ -3598,7 +3612,7 @@
876
877 <h4>Description</h4>
878
879-<p>Return the maximum array element count in  the server for the specified IO
880+<p>Return the maximum array element count in the server for the specified IO
881 channel.</p>
882
883 <h4>Arguments</h4>
884@@ -3610,7 +3624,7 @@
885 <h4>Returns</h4>
886 <dl>
887 <dt><code>COUNT</code></dt>
888- <dd>The maximum array element count in  the server. An element count of
889+ <dd>The maximum array element count in the server. An element count of
890 zero is returned if the channel is disconnected.</dd>
891 </dl>
892
893@@ -3641,7 +3655,7 @@
894
895 <h4>Description</h4>
896
897-<p>Set a user private void pointer variable retained with each channel for use
898+<p>Set a user private void pointer variable retained with each channel for use
899 at the users discretion.</p>
900
901 <h4>Arguments</h4>
902@@ -3750,8 +3764,8 @@
903
904 <h4>Description</h4>
905
906-<p>Returns boolean true if the client currently has read access to the
907-specified channel and boolean false otherwise.</p>
908+<p>Returns boolean true if the client currently has read access to the
909+specified channel and boolean false otherwise.</p>
910
911 <h4>Arguments</h4>
912 <dl>
913@@ -3762,8 +3776,8 @@
914 <h4>Returns</h4>
915 <dl>
916 <dt><code>STRING</code></dt>
917- <dd>boolean true if the client currently has read access to the specified
918- channel and boolean false otherwise</dd>
919+ <dd>boolean true if the client currently has read access to the specified
920+ channel and boolean false otherwise</dd>
921 </dl>
922
923 <h3><code><a name="L6941">ca_write_access()</a></code></h3>
924@@ -3772,8 +3786,8 @@
925
926 <h4>Description</h4>
927
928-<p>Returns boolean true if the client currently has write access to the
929-specified channel and boolean false otherwise.</p>
930+<p>Returns boolean true if the client currently has write access to the
931+specified channel and boolean false otherwise.</p>
932
933 <h4>Arguments</h4>
934 <dl>
935@@ -3784,8 +3798,8 @@
936 <h4>Returns</h4>
937 <dl>
938 <dt><code>STRING</code></dt>
939- <dd>boolean true if the client currently has write access to the specified
940- channel and boolean false otherwise</dd>
941+ <dd>boolean true if the client currently has write access to the specified
942+ channel and boolean false otherwise</dd>
943 </dl>
944
945 <h3><code><a name="dbr_size[]">dbr_size[]</a></code></h3>
946@@ -3794,12 +3808,12 @@
947
948 <h4>Description</h4>
949
950-<p>An array that returns the size in bytes for a DBR_XXXX type.</p>
951+<p>An array that returns the size in bytes for a DBR_XXXX type.</p>
952
953 <h4>Arguments</h4>
954 <dl>
955 <dt><code>TYPE</code></dt>
956- <dd>The data type code. A member of the set of DBF_XXXX in db_access.h.</dd>
957+ <dd>The data type code. A member of the set of DBF_XXXX in db_access.h.</dd>
958 </dl>
959
960 <h4>Returns</h4>
961@@ -3814,7 +3828,7 @@
962
963 <h4>Description</h4>
964
965-<p>Returns the size in bytes for a DBR_XXXX type with COUNT elements. If the
966+<p>Returns the size in bytes for a DBR_XXXX type with COUNT elements. If the
967 DBR type is a structure then the value field is the last field in the
968 structure. If COUNT is greater than one then COUNT-1 elements are appended to
969 the end of the structure so that they can be addressed as an array through a
970@@ -3850,7 +3864,7 @@
971 <h4>Arguments</h4>
972 <dl>
973 <dt><code>TYPE</code></dt>
974- <dd>The data type code. A member of the set of DBF_XXXX in db_access.h.</dd>
975+ <dd>The data type code. A member of the set of DBF_XXXX in db_access.h.</dd>
976 </dl>
977
978 <h4>Returns</h4>
979@@ -3872,7 +3886,7 @@
980 <h4>Arguments</h4>
981 <dl>
982 <dt><code>TYPE</code></dt>
983- <dd>The data type code. A member of the set of DBR_XXXX in db_access.h.</dd>
984+ <dd>The data type code. A member of the set of DBR_XXXX in db_access.h.</dd>
985 </dl>
986
987 <h4>Returns</h4>
988@@ -3937,7 +3951,7 @@
989 <p>ECA_ALLOCMEM - Failed, unable to allocate memory</p>
990
991 <h4>See Also</h4>
992-ca_sg_delete()
993+ca_sg_delete()
994
995 <p>ca_sg_block()</p>
996
997@@ -3996,7 +4010,7 @@
998
999 <p>Values written into your program's variables by a channel access synchronous
1000 group request should not be referenced by your program until ECA_NORMAL has
1001-been received from ca_sg_block(). This routine will process pending channel
1002+been received from ca_sg_block(). This routine will process pending channel
1003 access background activity while it is waiting.</p>
1004
1005 <h4>Arguments</h4>
1006@@ -4028,7 +4042,7 @@
1007
1008 <h3><code><a name="ca_sg_test">ca_sg_test()</a></code></h3>
1009 <pre><code>#include &lt;cadef.h&gt;
1010-int ca_sg_test  ( CA_SYNC_GID GID )</code></pre>
1011+int ca_sg_test ( CA_SYNC_GID GID )</code></pre>
1012
1013 <h4>Description</h4>
1014
1015@@ -4087,7 +4101,7 @@
1016 int ca_sg_array_put ( CA_SYNC_GID GID, chtype TYPE,
1017 unsigned long COUNT, chid CHID, void *PVALUE );</code></pre>
1018
1019-<p>Write a value, or array of values, to a channel and increment the
1020+<p>Write a value, or array of values, to a channel and increment the
1021 outstanding request count of a synchronous group. The ca_sg_array_put
1022 functionality is implemented using ca_array_put_callback.</p>
1023
1024@@ -4157,8 +4171,8 @@
1025 ca_array_get_callback.</p>
1026
1027 <p>The values written into your program's variables by ca_sg_get should not be
1028-referenced by your program until ECA_NORMAL has been received from ca_sg_block
1029-, or until ca_sg_test returns ECA_IODONE.</p>
1030+referenced by your program until ECA_NORMAL has been received from ca_sg_block,
1031+or until ca_sg_test returns ECA_IODONE.</p>
1032
1033 <p>All remote operation requests such as the above are accumulated (buffered)
1034 and not forwarded to the server until one of ca_flush_io, ca_pend_io,
1035@@ -4186,7 +4200,7 @@
1036 </dl>
1037 <dl>
1038 <dt><code>CHID</code></dt>
1039- <dd>channel identifier</dd>
1040+ <dd>channel identifier</dd>
1041 </dl>
1042 <dl>
1043 <dt><code>PVALUE</code></dt>
1044@@ -4196,9 +4210,9 @@
1045
1046 <h4>Returns</h4>
1047
1048-<p>ECA_NORMAL - Normal successful completion </p>
1049+<p>ECA_NORMAL - Normal successful completion�</p>
1050
1051-<p>ECA_BADSYNCGRP - Invalid synchronous group </p>
1052+<p>ECA_BADSYNCGRP - Invalid synchronous group�</p>
1053
1054 <p>ECA_BADCHID - Corrupted CHID</p>
1055
1056@@ -4224,7 +4238,7 @@
1057 <h4>Description</h4>
1058
1059 <p>Prints information about the client context including, at higher interest
1060-levels, status for each channel. Lacking a CA context pointer,
1061+levels, status for each channel. Lacking a CA context pointer,
1062 ca_client_status() prints information about the calling threads CA context.</p>
1063
1064 <h4>Arguments</h4>
1065@@ -4404,7 +4418,6 @@
1066 bytes</dd>
1067 </dl>
1068
1069-<p><small>$Id$
1070-.</small></p>
1071+<p></p>
1072 </body>
1073 </html>
1074
1075=== added file 'src/ca/SearchDest.h'
1076--- src/ca/SearchDest.h 1970-01-01 00:00:00 +0000
1077+++ src/ca/SearchDest.h 2010-05-14 13:38:34 +0000
1078@@ -0,0 +1,39 @@
1079+/*************************************************************************\
1080+ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
1081+ * National Laboratory.
1082+ * Copyright (c) 2002 The Regents of the University of California, as
1083+ * Operator of Los Alamos National Laboratory.
1084+ * EPICS BASE Versions 3.13.7
1085+ * and higher are distributed subject to a Software License Agreement found
1086+ * in file LICENSE that is included with this distribution.
1087+\*************************************************************************/
1088+
1089+#ifndef SearchDest_h
1090+#define SearchDest_h
1091+
1092+#include <osiSock.h>
1093+#include <epicsTime.h>
1094+#include <tsDLList.h>
1095+#include "caProto.h"
1096+
1097+class channelNode;
1098+class epicsMutex;
1099+template < class T > class epicsGuard;
1100+
1101+struct SearchDest :
1102+ public tsDLNode < SearchDest > {
1103+ virtual ~SearchDest () {};
1104+ struct Callback {
1105+ virtual ~Callback () {};
1106+ virtual void notify (
1107+ const caHdr & msg, const void * pPayload,
1108+ const osiSockAddr & addr, const epicsTime & ) = 0;
1109+ virtual void show (
1110+ epicsGuard < epicsMutex > &, unsigned level ) const = 0;
1111+ };
1112+ virtual void searchRequest ( epicsGuard < epicsMutex > &,
1113+ const char * pbuf, size_t len ) = 0;
1114+ virtual void show ( epicsGuard < epicsMutex > &, unsigned level ) const = 0;
1115+};
1116+
1117+#endif // SearchDest_h
1118
1119=== modified file 'src/ca/caProto.h'
1120--- src/ca/caProto.h 2004-10-04 18:55:40 +0000
1121+++ src/ca/caProto.h 2010-05-14 13:38:34 +0000
1122@@ -40,6 +40,7 @@
1123 # define CA_V49(MINOR) ((MINOR)>=9u) /* large arrays, dispatch priorities */
1124 # define CA_V410(MINOR) ((MINOR)>=10u) /* beacon counter */
1125 # define CA_V411(MINOR) ((MINOR)>=11u) /* sequence numbers in UDP version command */
1126+# define CA_V412(MINOR) ((MINOR)>=12u) /* TCP-based search requests */
1127 #elif CA_MAJOR_PROTOCOL_REVISION > 4u
1128 # define CA_V41(MINOR) ( 1u )
1129 # define CA_V42(MINOR) ( 1u )
1130@@ -52,6 +53,7 @@
1131 # define CA_V49(MINOR) ( 1u )
1132 # define CA_V410(MINOR) ( 1u )
1133 # define CA_V411(MINOR) ( 1u )
1134+# define CA_V412(MINOR) ( 1u )
1135 #else
1136 # define CA_V41(MINOR) ( 0u )
1137 # define CA_V42(MINOR) ( 0u )
1138@@ -64,7 +66,8 @@
1139 # define CA_V49(MINOR) ( 0u )
1140 # define CA_V410(MINOR) ( 0u )
1141 # define CA_V411(MINOR) ( 0u )
1142-#endif
1143+# define CA_V412(MINOR) ( 0u )
1144+#endif
1145
1146 /*
1147 * These port numbers are only used if the CA repeater and
1148
1149=== modified file 'src/ca/ca_client_context.cpp'
1150--- src/ca/ca_client_context.cpp 2009-08-21 00:53:55 +0000
1151+++ src/ca/ca_client_context.cpp 2010-05-14 13:38:34 +0000
1152@@ -1,12 +1,13 @@
1153 /*************************************************************************\
1154-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
1155-* National Laboratory.
1156-* Copyright (c) 2002 The Regents of the University of California, as
1157-* Operator of Los Alamos National Laboratory.
1158-* EPICS BASE Versions 3.13.7
1159-* and higher are distributed subject to a Software License Agreement found
1160-* in file LICENSE that is included with this distribution.
1161+ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
1162+ * National Laboratory.
1163+ * Copyright (c) 2002 The Regents of the University of California, as
1164+ * Operator of Los Alamos National Laboratory.
1165+ * EPICS BASE Versions 3.13.7
1166+ * and higher are distributed subject to a Software License Agreement found
1167+ * in file LICENSE that is included with this distribution.
1168 \*************************************************************************/
1169+
1170 /*
1171 *
1172 *
1173
1174=== modified file 'src/ca/cac.cpp'
1175--- src/ca/cac.cpp 2009-08-14 16:56:31 +0000
1176+++ src/ca/cac.cpp 2010-05-14 13:38:34 +0000
1177@@ -1,14 +1,14 @@
1178 /*************************************************************************\
1179-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
1180-* National Laboratory.
1181-* Copyright (c) 2002 The Regents of the University of California, as
1182-* Operator of Los Alamos National Laboratory.
1183-* EPICS BASE Versions 3.13.7
1184-* and higher are distributed subject to a Software License Agreement found
1185-* in file LICENSE that is included with this distribution.
1186+ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
1187+ * National Laboratory.
1188+ * Copyright (c) 2002 The Regents of the University of California, as
1189+ * Operator of Los Alamos National Laboratory.
1190+ * EPICS BASE Versions 3.13.7
1191+ * and higher are distributed subject to a Software License Agreement found
1192+ * in file LICENSE that is included with this distribution.
1193 \*************************************************************************/
1194-/*
1195- *
1196+
1197+/*
1198 * L O S A L A M O S
1199 * Los Alamos National Laboratory
1200 * Los Alamos, New Mexico 87545
1201@@ -16,6 +16,7 @@
1202 * Copyright, 1986, The Regents of the University of California.
1203 *
1204 * Author: Jeff Hill
1205+ *
1206 */
1207
1208 #define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
1209@@ -34,6 +35,7 @@
1210 #include "errlog.h"
1211
1212 #define epicsExportSharedSymbols
1213+#include "addrList.h"
1214 #include "iocinf.h"
1215 #include "cac.h"
1216 #include "inetAddrID.h"
1217@@ -62,7 +64,7 @@
1218 &cac::readRespAction,
1219 &cac::badTCPRespAction,
1220 &cac::badTCPRespAction,
1221- &cac::badTCPRespAction,
1222+ &cac::searchRespAction,
1223 &cac::badTCPRespAction,
1224 &cac::badTCPRespAction,
1225 &cac::badTCPRespAction,
1226@@ -177,6 +179,10 @@
1227 strncpy ( this->pUserName, tmp, len );
1228 }
1229
1230+ this->_serverPort =
1231+ envGetInetPortConfigParam ( &EPICS_CA_SERVER_PORT,
1232+ static_cast <unsigned short> (CA_SERVER_PORT) );
1233+
1234 status = envGetDoubleConfigParam ( &EPICS_CA_CONN_TMO, &this->connTMO );
1235 if ( status ) {
1236 this->connTMO = CA_CONN_VERIFY_PERIOD;
1237@@ -234,6 +240,34 @@
1238 this->timerQueue.release ();
1239 throw;
1240 }
1241+
1242+ /*
1243+ * load user configured tcp name server address list,
1244+ * create virtual circuits, and add them to server table
1245+ */
1246+ ELLLIST dest, tmpList;
1247+
1248+ ellInit ( & dest );
1249+ ellInit ( & tmpList );
1250+
1251+ addAddrToChannelAccessAddressList ( &tmpList, &EPICS_CA_NAME_SERVERS, this->_serverPort, false );
1252+ removeDuplicateAddresses ( &dest, &tmpList, 0 );
1253+
1254+ epicsGuard < epicsMutex > guard ( this->mutex );
1255+
1256+ while ( osiSockAddrNode *
1257+ pNode = reinterpret_cast < osiSockAddrNode * > ( ellGet ( & dest ) ) ) {
1258+ tcpiiu * piiu = NULL;
1259+ SearchDestTCP * pdst = new SearchDestTCP ( *this, pNode->addr );
1260+ this->registerSearchDest ( guard, * pdst );
1261+ bool newIIU = findOrCreateVirtCircuit (
1262+ guard, pNode->addr, cacChannel::priorityDefault,
1263+ piiu, CA_UKN_MINOR_VERSION, pdst );
1264+ free ( pNode );
1265+ if ( newIIU ) {
1266+ piiu->start ( guard );
1267+ }
1268+ }
1269 }
1270
1271 cac::~cac ()
1272@@ -468,7 +502,8 @@
1273 if ( ! this->pudpiiu ) {
1274 this->pudpiiu = new udpiiu (
1275 guard, this->timerQueue, this->cbMutex,
1276- this->mutex, this->notify, *this );
1277+ this->mutex, this->notify, *this, this->_serverPort,
1278+ this->searchDestList );
1279 }
1280
1281 nciu * pNetChan = new ( this->channelFreeList )
1282@@ -477,6 +512,57 @@
1283 return *pNetChan;
1284 }
1285
1286+bool cac::findOrCreateVirtCircuit (
1287+ epicsGuard < epicsMutex > & guard, const osiSockAddr & addr,
1288+ unsigned priority, tcpiiu *& piiu, unsigned minorVersionNumber,
1289+ SearchDestTCP * pSearchDest )
1290+{
1291+ guard.assertIdenticalMutex ( this->mutex );
1292+ bool newIIU = false;
1293+
1294+ if ( piiu ) {
1295+ if ( ! piiu->alive ( guard ) ) {
1296+ return newIIU;
1297+ }
1298+ }
1299+ else {
1300+ try {
1301+ autoPtrFreeList < tcpiiu, 32, epicsMutexNOOP > pnewiiu (
1302+ this->freeListVirtualCircuit,
1303+ new ( this->freeListVirtualCircuit ) tcpiiu (
1304+ *this, this->mutex, this->cbMutex, this->notify, this->connTMO,
1305+ this->timerQueue, addr, this->comBufMemMgr, minorVersionNumber,
1306+ this->ipToAEngine, priority, pSearchDest ) );
1307+
1308+ bhe * pBHE = this->beaconTable.lookup ( addr.ia );
1309+ if ( ! pBHE ) {
1310+ pBHE = new ( this->bheFreeList )
1311+ bhe ( this->mutex, epicsTime (), 0u, addr.ia );
1312+ if ( this->beaconTable.add ( *pBHE ) < 0 ) {
1313+ return newIIU;
1314+ }
1315+ }
1316+ this->serverTable.add ( *pnewiiu );
1317+ this->circuitList.add ( *pnewiiu );
1318+ pBHE->registerIIU ( guard, *pnewiiu );
1319+ piiu = pnewiiu.release ();
1320+ newIIU = true;
1321+ }
1322+ catch ( std :: exception & except ) {
1323+ errlogPrintf (
1324+ "CAC: exception during virtual circuit creation \"%s\"\n",
1325+ except.what () );
1326+ return newIIU;
1327+ }
1328+ catch ( ... ) {
1329+ errlogPrintf (
1330+ "CAC: Nonstandard exception during virtual circuit creation\n" );
1331+ return newIIU;
1332+ }
1333+ }
1334+ return newIIU;
1335+}
1336+
1337 void cac::transferChanToVirtCircuit (
1338 unsigned cid, unsigned sid, // X aCC 431
1339 ca_uint16_t typeCode, arrayElementCount count,
1340@@ -484,7 +570,7 @@
1341 const epicsTime & currentTime )
1342 {
1343 if ( addr.sa.sa_family != AF_INET ) {
1344- return ;
1345+ return;
1346 }
1347
1348 epicsGuard < epicsMutex > guard ( this->mutex );
1349@@ -501,6 +587,7 @@
1350 * Ignore duplicate search replies
1351 */
1352 osiSockAddr chanAddr = pChan->getPIIU(guard)->getNetworkAddress (guard);
1353+
1354 if ( chanAddr.sa.sa_family != AF_UNSPEC ) {
1355 if ( ! sockAddrAreIdentical ( &addr, &chanAddr ) ) {
1356 char acc[64];
1357@@ -519,52 +606,12 @@
1358 return;
1359 }
1360
1361- /*
1362- * look for an existing virtual circuit
1363- */
1364- bool newIIU = false;
1365 caServerID servID ( addr.ia, pChan->getPriority(guard) );
1366 tcpiiu * piiu = this->serverTable.lookup ( servID );
1367- if ( piiu ) {
1368- if ( ! piiu->alive ( guard ) ) {
1369- return;
1370- }
1371- }
1372- else {
1373- try {
1374- autoPtrFreeList < tcpiiu, 32, epicsMutexNOOP > pnewiiu (
1375- this->freeListVirtualCircuit,
1376- new ( this->freeListVirtualCircuit ) tcpiiu (
1377- *this, this->mutex, this->cbMutex, this->notify, this->connTMO,
1378- this->timerQueue, addr, this->comBufMemMgr, minorVersionNumber,
1379- this->ipToAEngine, pChan->getPriority(guard) ) );
1380- bhe * pBHE = this->beaconTable.lookup ( addr.ia );
1381- if ( ! pBHE ) {
1382- pBHE = new ( this->bheFreeList )
1383- bhe ( this->mutex, epicsTime (), 0u, addr.ia );
1384- if ( this->beaconTable.add ( *pBHE ) < 0 ) {
1385- return;
1386- }
1387- }
1388- this->serverTable.add ( *pnewiiu );
1389- this->circuitList.add ( *pnewiiu );
1390- this->iiuExistenceCount++;
1391- pBHE->registerIIU ( guard, *pnewiiu );
1392- piiu = pnewiiu.release ();
1393- newIIU = true;
1394- }
1395- catch ( std :: exception & except ) {
1396- errlogPrintf (
1397- "CAC: exception during virtual circuit creation \"%s\"\n",
1398- except.what () );
1399- return;
1400- }
1401- catch ( ... ) {
1402- errlogPrintf (
1403- "CAC: nonstandard exception during virtual circuit creation\n" );
1404- return;
1405- }
1406- }
1407+
1408+ bool newIIU = findOrCreateVirtCircuit (
1409+ guard, addr,
1410+ pChan->getPriority(guard), piiu, minorVersionNumber, false );
1411
1412 // must occur before moving to new iiu
1413 pChan->getPIIU(guard)->uninstallChanDueToSuccessfulSearchResponse (
1414@@ -746,9 +793,10 @@
1415 return *pIO.release ();
1416 }
1417
1418-bool cac::versionAction ( callbackManager &, tcpiiu &,
1419- const epicsTime &, const caHdrLargeArray &, void * )
1420+bool cac::versionAction ( callbackManager &, tcpiiu & iiu,
1421+ const epicsTime &, const caHdrLargeArray & msg, void * )
1422 {
1423+ iiu.versionRespNotify ( msg );
1424 return true;
1425 }
1426
1427@@ -831,6 +879,15 @@
1428 return true;
1429 }
1430
1431+bool cac::searchRespAction ( callbackManager &, tcpiiu & iiu,
1432+ const epicsTime & currentTime, const caHdrLargeArray & msg,
1433+ void * /* pMsgBdy */ )
1434+{
1435+ assert ( this->pudpiiu );
1436+ iiu.searchRespNotify ( currentTime, msg );
1437+ return true;
1438+}
1439+
1440 bool cac::eventRespAction ( callbackManager &, tcpiiu &iiu,
1441 const epicsTime &, const caHdrLargeArray & hdr, void * pMsgBdy )
1442 {
1443@@ -1076,7 +1133,7 @@
1444 }
1445
1446 bool cac::verifyAndDisconnectChan (
1447- callbackManager & mgr, tcpiiu &,
1448+ callbackManager & mgr, tcpiiu &,
1449 const epicsTime &, const caHdrLargeArray & hdr, void * /* pMsgBody */ )
1450 {
1451 epicsGuard < epicsMutex > guard ( this->mutex );
1452@@ -1139,6 +1196,7 @@
1453 {
1454 callbackManager mgr ( this->notify, this->cbMutex );
1455 epicsGuard < epicsMutex > guard ( this->mutex );
1456+
1457 if ( iiu.channelCount ( guard ) ) {
1458 char hostNameTmp[64];
1459 iiu.getHostName ( guard, hostNameTmp, sizeof ( hostNameTmp ) );
1460@@ -1166,13 +1224,14 @@
1461 // this waits for send/recv threads to exit
1462 // this also uses the cac free lists so cac must wait
1463 // for this to finish before it shuts down
1464+
1465 iiu.~tcpiiu ();
1466
1467 {
1468 epicsGuard < epicsMutex > guard ( this->mutex );
1469 this->freeListVirtualCircuit.release ( & iiu );
1470 this->iiuExistenceCount--;
1471- // signal iiu uninstal event so that cac can properly shut down
1472+ // signal iiu uninstall event so that cac can properly shut down
1473 this->iiuUninstall.signal();
1474 }
1475 // do not touch "this" after lock is released above
1476@@ -1230,3 +1289,10 @@
1477 this->mdpvFreeList.release ( & mfmdpv );
1478 }
1479
1480+void cac::registerSearchDest (
1481+ epicsGuard < epicsMutex > & guard,
1482+ SearchDest & req )
1483+{
1484+ guard.assertIdenticalMutex ( this->mutex );
1485+ this->searchDestList.add ( req );
1486+}
1487
1488=== modified file 'src/ca/cac.h'
1489--- src/ca/cac.h 2009-08-13 23:29:02 +0000
1490+++ src/ca/cac.h 2010-05-14 13:38:34 +0000
1491@@ -1,25 +1,23 @@
1492 /*************************************************************************\
1493-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
1494-* National Laboratory.
1495-* Copyright (c) 2002 The Regents of the University of California, as
1496-* Operator of Los Alamos National Laboratory.
1497-* EPICS BASE Versions 3.13.7
1498-* and higher are distributed subject to a Software License Agreement found
1499-* in file LICENSE that is included with this distribution.
1500+ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
1501+ * National Laboratory.
1502+ * Copyright (c) 2002 The Regents of the University of California, as
1503+ * Operator of Los Alamos National Laboratory.
1504+ * EPICS BASE Versions 3.13.7
1505+ * and higher are distributed subject to a Software License Agreement found
1506+ * in file LICENSE that is included with this distribution.
1507 \*************************************************************************/
1508-/*
1509- *
1510- *
1511+
1512+/*
1513 * L O S A L A M O S
1514 * Los Alamos National Laboratory
1515 * Los Alamos, New Mexico 87545
1516- *
1517+ *
1518 * Copyright, 1986, The Regents of the University of California.
1519- *
1520- *
1521- * Author Jeffrey O. Hill
1522- * johill@lanl.gov
1523- * 505 665 1831
1524+ *
1525+ *
1526+ * Author: Jeff Hill
1527+ *
1528 */
1529
1530 #ifndef cach
1531@@ -182,6 +180,13 @@
1532 int status, const char * pContext,
1533 const char * pFileName, unsigned lineNo );
1534
1535+ // search destination management
1536+ void registerSearchDest (
1537+ epicsGuard < epicsMutex > &, SearchDest & req );
1538+ bool findOrCreateVirtCircuit (
1539+ epicsGuard < epicsMutex > &, const osiSockAddr &,
1540+ unsigned, tcpiiu *&, unsigned, SearchDestTCP * pSearchDest = NULL );
1541+
1542 // diagnostics
1543 unsigned circuitCount ( epicsGuard < epicsMutex > & ) const;
1544 void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
1545@@ -191,6 +196,7 @@
1546 int varArgsPrintFormated (
1547 epicsGuard < epicsMutex > & callbackControl,
1548 const char *pformat, va_list args ) const;
1549+ double connectionTimeout ( epicsGuard < epicsMutex > & );
1550
1551 // buffer management
1552 char * allocateSmallBufferTCP ();
1553@@ -235,6 +241,7 @@
1554 resTable < bhe, inetAddrID > beaconTable;
1555 resTable < tcpiiu, caServerID > serverTable;
1556 tsDLList < tcpiiu > circuitList;
1557+ tsDLList < SearchDest > searchDestList;
1558 tsFreeList
1559 < class tcpiiu, 32, epicsMutexNOOP >
1560 freeListVirtualCircuit;
1561@@ -275,6 +282,7 @@
1562 unsigned maxRecvBytesTCP;
1563 unsigned maxContigFrames;
1564 unsigned beaconAnomalyCount;
1565+ unsigned short _serverPort;
1566 unsigned iiuExistenceCount;
1567
1568 void recycleReadNotifyIO (
1569@@ -303,6 +311,8 @@
1570 const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
1571 bool writeNotifyRespAction ( callbackManager &, tcpiiu &,
1572 const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
1573+ bool searchRespAction ( callbackManager &, tcpiiu &,
1574+ const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
1575 bool readNotifyRespAction ( callbackManager &, tcpiiu &,
1576 const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
1577 bool eventRespAction ( callbackManager &, tcpiiu &,
1578@@ -444,11 +454,17 @@
1579 return _refLocalHostName->pointer ();
1580 }
1581
1582-inline unsigned cac ::
1583+inline unsigned cac ::
1584 maxContiguousFrames ( epicsGuard < epicsMutex > & ) const
1585 {
1586 return maxContigFrames;
1587+}
1588+
1589+inline double cac ::
1590+ connectionTimeout ( epicsGuard < epicsMutex > & guard )
1591+{
1592+ guard.assertIdenticalMutex ( this->mutex );
1593+ return this->connTMO;
1594 }
1595
1596 #endif // ifdef cach
1597-
1598
1599=== modified file 'src/ca/iocinf.cpp'
1600--- src/ca/iocinf.cpp 2009-08-04 19:10:30 +0000
1601+++ src/ca/iocinf.cpp 2010-05-14 13:38:34 +0000
1602@@ -1,12 +1,13 @@
1603 /*************************************************************************\
1604-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
1605-* National Laboratory.
1606-* Copyright (c) 2002 The Regents of the University of California, as
1607-* Operator of Los Alamos National Laboratory.
1608-* EPICS BASE Versions 3.13.7
1609-* and higher are distributed subject to a Software License Agreement found
1610-* in file LICENSE that is included with this distribution.
1611+ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
1612+ * National Laboratory.
1613+ * Copyright (c) 2002 The Regents of the University of California, as
1614+ * Operator of Los Alamos National Laboratory.
1615+ * EPICS BASE Versions 3.13.7
1616+ * and higher are distributed subject to a Software License Agreement found
1617+ * in file LICENSE that is included with this distribution.
1618 \*************************************************************************/
1619+
1620 /*
1621 *
1622 * L O S A L A M O S
1623
1624=== modified file 'src/ca/nciu.h'
1625--- src/ca/nciu.h 2008-07-28 16:19:50 +0000
1626+++ src/ca/nciu.h 2010-05-14 13:38:34 +0000
1627@@ -41,7 +41,7 @@
1628 # include "shareLib.h"
1629 #endif
1630
1631-#define CA_MINOR_PROTOCOL_REVISION 11
1632+#define CA_MINOR_PROTOCOL_REVISION 12
1633 #include "caProto.h"
1634
1635 #include "cacIO.h"
1636
1637=== modified file 'src/ca/tcpiiu.cpp'
1638--- src/ca/tcpiiu.cpp 2009-09-11 00:49:02 +0000
1639+++ src/ca/tcpiiu.cpp 2010-05-14 13:38:34 +0000
1640@@ -1,16 +1,14 @@
1641 /*************************************************************************\
1642-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
1643-* National Laboratory.
1644-* Copyright (c) 2002 The Regents of the University of California, as
1645-* Operator of Los Alamos National Laboratory.
1646-* EPICS BASE Versions 3.13.7
1647-* and higher are distributed subject to a Software License Agreement found
1648-* in file LICENSE that is included with this distribution.
1649+ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
1650+ * National Laboratory.
1651+ * Copyright (c) 2002 The Regents of the University of California, as
1652+ * Operator of Los Alamos National Laboratory.
1653+ * EPICS BASE Versions 3.13.7
1654+ * and higher are distributed subject to a Software License Agreement found
1655+ * in file LICENSE that is included with this distribution.
1656 \*************************************************************************/
1657
1658-
1659 /*
1660- *
1661 * L O S A L A M O S
1662 * Los Alamos National Laboratory
1663 * Los Alamos, New Mexico 87545
1664@@ -18,6 +16,7 @@
1665 * Copyright, 1986, The Regents of the University of California.
1666 *
1667 * Author: Jeff Hill
1668+ *
1669 */
1670
1671 #ifdef _MSC_VER
1672@@ -228,7 +227,6 @@
1673 epicsThreadSleep ( 0.1 );
1674 }
1675 }
1676-
1677 this->iiu.cacRef.destroyIIU ( this->iiu );
1678 }
1679
1680@@ -236,7 +234,6 @@
1681 unsigned nBytesInBuf, const epicsTime & currentTime )
1682 {
1683 unsigned nBytes = 0u;
1684-
1685 assert ( nBytesInBuf <= INT_MAX );
1686
1687 this->sendDog.start ( currentTime );
1688@@ -453,6 +450,10 @@
1689 this->iiu.cacRef.destroyIIU ( this->iiu );
1690 return;
1691 }
1692+ if ( this->iiu.isNameService () ) {
1693+ this->iiu.pSearchDest->setCircuit ( &this->iiu );
1694+ this->iiu.pSearchDest->enable ();
1695+ }
1696 }
1697
1698 this->iiu.sendThread.start ();
1699@@ -477,7 +478,7 @@
1700 pComBuf->fillFromWire ( this->iiu, stat );
1701
1702 epicsTime currentTime = epicsTime::getCurrent ();
1703-
1704+
1705 {
1706 epicsGuard < epicsMutex > guard ( this->iiu.mutex );
1707
1708@@ -634,17 +635,27 @@
1709 continue;
1710 }
1711 else if ( errnoCpy == SOCK_SHUTDOWN ) {
1712- break;
1713+ if ( ! this->iiu.isNameService () ) {
1714+ break;
1715+ }
1716 }
1717- else {
1718+ else {
1719 char sockErrBuf[64];
1720 epicsSocketConvertErrnoToString (
1721 sockErrBuf, sizeof ( sockErrBuf ) );
1722- errlogPrintf ( "CAC: Unable to connect because \"%s\"\n",
1723+ errlogPrintf ( "CAC: Unable to connect because \"%s\"\n",
1724 sockErrBuf );
1725- this->iiu.disconnectNotify ( guard );
1726- break;
1727- }
1728+ if ( ! this->iiu.isNameService () ) {
1729+ this->iiu.disconnectNotify ( guard );
1730+ break;
1731+ }
1732+ }
1733+ {
1734+ double sleepTime = this->iiu.cacRef.connectionTimeout ( guard );
1735+ epicsGuardRelease < epicsMutex > unguard ( guard );
1736+ epicsThreadSleep ( sleepTime );
1737+ }
1738+ continue;
1739 }
1740 }
1741 return;
1742@@ -659,7 +670,8 @@
1743 epicsTimerQueue & timerQueue, const osiSockAddr & addrIn,
1744 comBufMemoryManager & comBufMemMgrIn,
1745 unsigned minorVersion, ipAddrToAsciiEngine & engineIn,
1746- const cacChannel::priLev & priorityIn ) :
1747+ const cacChannel::priLev & priorityIn,
1748+ SearchDestTCP * pSearchDestIn ) :
1749 caServerID ( addrIn.ia, priorityIn ),
1750 hostNameCacheInstance ( addrIn, engineIn ),
1751 recvThread ( *this, cbMutexIn, ctxNotifyIn, "CAC-TCP-recv",
1752@@ -680,6 +692,7 @@
1753 comBufMemMgr ( comBufMemMgrIn ),
1754 cacRef ( cac ),
1755 pCurData ( cac.allocateSmallBufferTCP () ),
1756+ pSearchDest ( pSearchDestIn ),
1757 mutex ( mutexIn ),
1758 cbMutex ( cbMutexIn ),
1759 minorProtocolVersion ( minorVersion ),
1760@@ -815,6 +828,10 @@
1761 }
1762 # endif
1763
1764+ if ( isNameService() ) {
1765+ pSearchDest->setCircuit ( this );
1766+ }
1767+
1768 memset ( (void *) &this->curMsg, '\0', sizeof ( this->curMsg ) );
1769 }
1770
1771@@ -831,6 +848,7 @@
1772 epicsGuard < epicsMutex > & guard )
1773 {
1774 guard.assertIdenticalMutex ( this->mutex );
1775+
1776 if ( this->state == iiucs_connected ) {
1777 if ( this->unresponsiveCircuit ) {
1778 this->initiateAbortShutdown ( guard );
1779@@ -1014,8 +1032,12 @@
1780 //
1781 // tcpiiu::~tcpiiu ()
1782 //
1783-tcpiiu::~tcpiiu ()
1784+tcpiiu :: ~tcpiiu ()
1785 {
1786+ if ( this->pSearchDest ) {
1787+ this->pSearchDest->disable ();
1788+ }
1789+
1790 this->sendThread.exitWait ();
1791 this->recvThread.exitWait ();
1792 this->sendDog.cancel ();
1793@@ -1830,7 +1852,9 @@
1794
1795 this->channelCountTot = 0u;
1796
1797- this->initiateCleanShutdown ( guard );
1798+ if ( ! isNameService () ) {
1799+ this->initiateCleanShutdown ( guard );
1800+ }
1801 }
1802
1803 void tcpiiu::unlinkAllChannels (
1804@@ -1839,7 +1863,7 @@
1805 {
1806 cbGuard.assertIdenticalMutex ( this->cbMutex );
1807 guard.assertIdenticalMutex ( this->mutex );
1808-
1809+
1810 while ( nciu * pChan = this->createReqPend.get () ) {
1811 pChan->serviceShutdownNotify ( cbGuard, guard );
1812 }
1813@@ -1890,7 +1914,9 @@
1814
1815 this->channelCountTot = 0u;
1816
1817- this->initiateCleanShutdown ( guard );
1818+ if ( ! isNameService () ) {
1819+ this->initiateCleanShutdown ( guard );
1820+ }
1821 }
1822
1823 void tcpiiu::installChannel (
1824@@ -1909,20 +1935,6 @@
1825 this->sendThreadFlushEvent.signal ();
1826 }
1827
1828-void tcpiiu::nameResolutionMsgEndNotify ()
1829-{
1830- bool wakeupNeeded = false;
1831- {
1832- epicsGuard < epicsMutex > autoMutex ( this->mutex );
1833- if ( this->createReqPend.count () ) {
1834- wakeupNeeded = true;
1835- }
1836- }
1837- if ( wakeupNeeded ) {
1838- this->sendThreadFlushEvent.signal ();
1839- }
1840-}
1841-
1842 bool tcpiiu :: connectNotify (
1843 epicsGuard < epicsMutex > & guard, nciu & chan )
1844 {
1845@@ -1980,7 +1992,7 @@
1846 }
1847 chan.channelNode::listMember = channelNode::cs_none;
1848 this->channelCountTot--;
1849- if ( this->channelCountTot == 0 ) {
1850+ if ( this->channelCountTot == 0 && ! this->isNameService() ) {
1851 this->initiateCleanShutdown ( guard );
1852 }
1853 }
1854@@ -2100,5 +2112,81 @@
1855 guard, id, pName, nameLength );
1856 }
1857
1858-
1859-
1860+SearchDestTCP :: SearchDestTCP (
1861+ cac & cacIn, const osiSockAddr & addrIn ) :
1862+ _ptcpiiu ( NULL ),
1863+ _cac ( cacIn ),
1864+ _addr ( addrIn ),
1865+ _active ( false )
1866+{
1867+}
1868+
1869+void SearchDestTCP :: disable ()
1870+{
1871+ _active = false;
1872+ _ptcpiiu = NULL;
1873+}
1874+
1875+void SearchDestTCP :: enable ()
1876+{
1877+ _active = true;
1878+}
1879+
1880+void SearchDestTCP :: searchRequest (
1881+ epicsGuard < epicsMutex > & guard,
1882+ const char * pBuf, size_t len )
1883+{
1884+ // restart circuit if it was shut down
1885+ if ( ! _ptcpiiu ) {
1886+ tcpiiu * piiu = NULL;
1887+ bool newIIU = _cac.findOrCreateVirtCircuit (
1888+ guard, _addr, cacChannel::priorityDefault,
1889+ piiu, CA_UKN_MINOR_VERSION, this );
1890+ if ( newIIU ) {
1891+ piiu->start ( guard );
1892+ }
1893+ _ptcpiiu = piiu;
1894+ }
1895+
1896+ // does this server support TCP-based name resolution?
1897+ if ( CA_V412 ( _ptcpiiu->minorProtocolVersion ) ) {
1898+ guard.assertIdenticalMutex ( _ptcpiiu->mutex );
1899+ assert ( CA_MESSAGE_ALIGN ( len ) == len );
1900+ comQueSendMsgMinder minder ( _ptcpiiu->sendQue, guard );
1901+ _ptcpiiu->sendQue.pushString ( pBuf, len );
1902+ minder.commit ();
1903+ _ptcpiiu->flushRequest ( guard );
1904+ }
1905+}
1906+
1907+void SearchDestTCP :: show (
1908+ epicsGuard < epicsMutex > & guard, unsigned level ) const
1909+{
1910+ :: printf ( "tcpiiu :: SearchDestTCP\n" );
1911+}
1912+
1913+void tcpiiu :: versionRespNotify ( const caHdrLargeArray & msg )
1914+{
1915+ this->minorProtocolVersion = msg.m_count;
1916+}
1917+
1918+void tcpiiu :: searchRespNotify (
1919+ const epicsTime & currentTime, const caHdrLargeArray & msg )
1920+{
1921+ /*
1922+ * the type field is abused to carry the port number
1923+ * so that we can have multiple servers on one host
1924+ */
1925+ osiSockAddr serverAddr;
1926+ if ( msg.m_cid != INADDR_BROADCAST ) {
1927+ serverAddr.ia.sin_family = AF_INET;
1928+ serverAddr.ia.sin_addr.s_addr = htonl ( msg.m_cid );
1929+ serverAddr.ia.sin_port = htons ( msg.m_dataType );
1930+ }
1931+ else {
1932+ serverAddr = this->address ();
1933+ }
1934+ cacRef.transferChanToVirtCircuit
1935+ ( msg.m_available, msg.m_cid, 0xffff,
1936+ 0, minorProtocolVersion, serverAddr, currentTime );
1937+}
1938
1939=== modified file 'src/ca/udpiiu.cpp'
1940--- src/ca/udpiiu.cpp 2009-07-09 17:06:45 +0000
1941+++ src/ca/udpiiu.cpp 2010-05-14 13:38:34 +0000
1942@@ -1,12 +1,13 @@
1943 /*************************************************************************\
1944-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
1945-* National Laboratory.
1946-* Copyright (c) 2002 The Regents of the University of California, as
1947-* Operator of Los Alamos National Laboratory.
1948-* EPICS BASE Versions 3.13.7
1949-* and higher are distributed subject to a Software License Agreement found
1950-* in file LICENSE that is included with this distribution.
1951+ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
1952+ * National Laboratory.
1953+ * Copyright (c) 2002 The Regents of the University of California, as
1954+ * Operator of Los Alamos National Laboratory.
1955+ * EPICS BASE Versions 3.13.7
1956+ * and higher are distributed subject to a Software License Agreement found
1957+ * in file LICENSE that is included with this distribution.
1958 \*************************************************************************/
1959+
1960 /*
1961 *
1962 * L O S A L A M O S
1963@@ -73,7 +74,9 @@
1964 epicsMutex & cbMutexIn,
1965 epicsMutex & cacMutexIn,
1966 cacContextNotify & ctxNotifyIn,
1967- cac & cac ) :
1968+ cac & cac,
1969+ unsigned port,
1970+ tsDLList < SearchDest > & searchDestListIn ) :
1971 recvThread ( *this, ctxNotifyIn, cbMutexIn, "CAC-UDP",
1972 epicsThreadGetStackSize ( epicsThreadStackMedium ),
1973 cac::lowestPriorityLevelAbove (
1974@@ -95,7 +98,7 @@
1975 lastReceivedSeqNo ( 0 ),
1976 sock ( 0 ),
1977 repeaterPort ( 0 ),
1978- serverPort ( 0 ),
1979+ serverPort ( port ),
1980 localPort ( 0 ),
1981 shutdownCmd ( false ),
1982 lastReceivedSeqNoIsValid ( false )
1983@@ -150,10 +153,6 @@
1984 envGetInetPortConfigParam ( &EPICS_CA_REPEATER_PORT,
1985 static_cast <unsigned short> (CA_REPEATER_PORT) );
1986
1987- this->serverPort =
1988- envGetInetPortConfigParam ( &EPICS_CA_SERVER_PORT,
1989- static_cast <unsigned short> (CA_SERVER_PORT) );
1990-
1991 this->sock = epicsSocketCreate ( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
1992 if ( this->sock == INVALID_SOCKET ) {
1993 char sockErrBuf[64];
1994@@ -238,8 +237,19 @@
1995 * load user and auto configured
1996 * broadcast address list
1997 */
1998- ellInit ( & this->dest ); // X aCC 392
1999- configureChannelAccessAddressList ( & this->dest, this->sock, this->serverPort );
2000+ ELLLIST dest;
2001+ ellInit ( & dest );
2002+ configureChannelAccessAddressList ( & dest, this->sock, this->serverPort );
2003+ while ( osiSockAddrNode *
2004+ pNode = reinterpret_cast < osiSockAddrNode * > ( ellGet ( & dest ) ) ) {
2005+ SearchDestUDP & searchDest = *
2006+ new SearchDestUDP ( pNode->addr, *this );
2007+ _searchDestList.add ( searchDest );
2008+ free ( pNode );
2009+ }
2010+
2011+ /* add list of tcp name service addresses */
2012+ _searchDestList.add ( searchDestListIn );
2013
2014 caStartRepeaterIfNotInstalled ( this->repeaterPort );
2015
2016@@ -265,14 +275,12 @@
2017 this->shutdown ( cbGuard, guard );
2018 }
2019
2020- // avoid use of ellFree because problems on windows occur if the
2021- // free is in a different DLL than the malloc
2022- ELLNODE * nnode = this->dest.node.next;
2023- while ( nnode )
2024+ tsDLIter < SearchDest > iter ( _searchDestList.firstIter () );
2025+ while ( iter.valid () )
2026 {
2027- ELLNODE * pnode = nnode;
2028- nnode = nnode->next;
2029- free ( pnode );
2030+ SearchDest & curr ( *iter );
2031+ iter++;
2032+ delete & curr;
2033 }
2034
2035 epicsSocketDestroy ( this->sock );
2036@@ -344,7 +352,7 @@
2037 {
2038 epicsThreadPrivateSet ( caClientCallbackThreadId, &this->iiu );
2039
2040- if ( ellCount ( & this->iiu.dest ) == 0 ) { // X aCC 392
2041+ if ( this->iiu._searchDestList.count () == 0 ) {
2042 callbackManager mgr ( this->ctxNotify, this->cbMutex );
2043 epicsGuard < epicsMutex > guard ( this->iiu.cacMutex );
2044 genLocalExcep ( mgr.cbGuard, guard,
2045@@ -614,26 +622,31 @@
2046 return true;
2047 }
2048
2049-bool udpiiu::searchRespAction ( // X aCC 361
2050- const caHdr &msg,
2051- const osiSockAddr & addr, const epicsTime & currentTime )
2052+bool udpiiu :: searchRespAction (
2053+ const caHdr & msg, const osiSockAddr & addr,
2054+ const epicsTime & currentTime )
2055 {
2056+ /*
2057+ * we dont currently know what to do with channel's
2058+ * found to be at non-IP type addresses
2059+ */
2060 if ( addr.sa.sa_family != AF_INET ) {
2061- return false;
2062+ return true;
2063 }
2064
2065 /*
2066 * Starting with CA V4.1 the minor version number
2067- * is appended to the end of each search reply.
2068+ * is appended to the end of each UDP search reply.
2069 * This value is ignored by earlier clients.
2070 */
2071 ca_uint32_t minorVersion;
2072- if ( msg.m_postsize >= sizeof (minorVersion) ){
2073+ if ( msg.m_postsize >= sizeof ( minorVersion ) ){
2074 /*
2075 * care is taken here not to break gcc 3.2 aggressive alias
2076 * analysis rules
2077 */
2078- ca_uint8_t * pPayLoad = ( ca_uint8_t *) ( &msg + 1 );
2079+ const ca_uint8_t * pPayLoad =
2080+ reinterpret_cast < const ca_uint8_t *> ( & msg + 1 );
2081 unsigned byte0 = pPayLoad[0];
2082 unsigned byte1 = pPayLoad[1];
2083 minorVersion = ( byte0 << 8u ) | byte1;
2084@@ -667,12 +680,12 @@
2085 }
2086
2087 if ( CA_V42 ( minorVersion ) ) {
2088- this->cacRef.transferChanToVirtCircuit
2089+ cacRef.transferChanToVirtCircuit
2090 ( msg.m_available, msg.m_cid, 0xffff,
2091 0, minorVersion, serverAddr, currentTime );
2092 }
2093 else {
2094- this->cacRef.transferChanToVirtCircuit
2095+ cacRef.transferChanToVirtCircuit
2096 ( msg.m_available, msg.m_cid, msg.m_dataType,
2097 msg.m_count, minorVersion, serverAddr, currentTime );
2098 }
2099@@ -895,62 +908,167 @@
2100 return true;
2101 }
2102
2103-bool udpiiu::datagramFlush (
2104- epicsGuard < epicsMutex > &, const epicsTime & /* currentTime */ )
2105-{
2106+udpiiu :: SearchDestUDP :: SearchDestUDP (
2107+ const osiSockAddr & destAddr, udpiiu & udpiiuIn ) :
2108+ _destAddr ( destAddr ), _udpiiu ( udpiiuIn )
2109+{
2110+}
2111+
2112+void udpiiu :: SearchDestUDP :: searchRequest (
2113+ epicsGuard < epicsMutex > & guard, const char * pBuf, size_t bufSize )
2114+{
2115+ guard.assertIdenticalMutex ( _udpiiu.cacMutex );
2116+ assert ( bufSize <= INT_MAX );
2117+ int bufSizeAsInt = static_cast < int > ( bufSize );
2118+ while ( true ) {
2119+ int status = sendto ( _udpiiu.sock, pBuf, bufSizeAsInt, 0,
2120+ & _destAddr.sa, sizeof ( _destAddr.sa ) );
2121+ if ( status == bufSizeAsInt ) {
2122+ break;
2123+ }
2124+ if ( status >= 0 ) {
2125+ errlogPrintf ( "CAC: UDP sendto () call returned strange xmit count?\n" );
2126+ break;
2127+ }
2128+ else {
2129+ int localErrno = SOCKERRNO;
2130+
2131+ if ( localErrno == SOCK_EINTR ) {
2132+ if ( _udpiiu.shutdownCmd ) {
2133+ break;
2134+ }
2135+ else {
2136+ continue;
2137+ }
2138+ }
2139+ else if ( localErrno == SOCK_SHUTDOWN ) {
2140+ break;
2141+ }
2142+ else if ( localErrno == SOCK_ENOTSOCK ) {
2143+ break;
2144+ }
2145+ else if ( localErrno == SOCK_EBADF ) {
2146+ break;
2147+ }
2148+ else {
2149+ char sockErrBuf[64];
2150+ epicsSocketConvertErrnoToString (
2151+ sockErrBuf, sizeof ( sockErrBuf ) );
2152+ char buf[64];
2153+ sockAddrToDottedIP ( &_destAddr.sa, buf, sizeof ( buf ) );
2154+ errlogPrintf (
2155+ "CAC: error = \"%s\" sending UDP msg to %s\n",
2156+ sockErrBuf, buf);
2157+ break;
2158+ }
2159+ }
2160+ }
2161+}
2162+
2163+void udpiiu :: SearchDestUDP :: show (
2164+ epicsGuard < epicsMutex > & guard, unsigned level ) const
2165+{
2166+ guard.assertIdenticalMutex ( _udpiiu.cacMutex );
2167+ char buf[64];
2168+ sockAddrToDottedIP ( &_destAddr.sa, buf, sizeof ( buf ) );
2169+ :: printf ( "UDP Search destination \"%s\"\n", buf );
2170+}
2171+
2172+udpiiu :: SearchRespCallback :: SearchRespCallback ( udpiiu & udpiiuIn ) :
2173+ _udpiiu ( udpiiuIn )
2174+{
2175+}
2176+
2177+void udpiiu :: SearchRespCallback :: notify (
2178+ const caHdr & msg, const void * pPayloadUntyped,
2179+ const osiSockAddr & addr, const epicsTime & currentTime )
2180+{
2181+ /*
2182+ * we dont currently know what to do with channel's
2183+ * found to be at non-IP type addresses
2184+ */
2185+ if ( addr.sa.sa_family != AF_INET ) {
2186+ return;
2187+ }
2188+
2189+ /*
2190+ * Starting with CA V4.1 the minor version number
2191+ * is appended to the end of each search reply.
2192+ * This value is ignored by earlier clients.
2193+ */
2194+ ca_uint32_t minorVersion;
2195+ if ( msg.m_postsize >= sizeof ( minorVersion ) ){
2196+ /*
2197+ * care is taken here not to break gcc 3.2 aggressive alias
2198+ * analysis rules
2199+ */
2200+ const ca_uint8_t * pPayLoad = reinterpret_cast < const ca_uint8_t *> ( pPayloadUntyped );
2201+ unsigned byte0 = pPayLoad[0];
2202+ unsigned byte1 = pPayLoad[1];
2203+ minorVersion = ( byte0 << 8u ) | byte1;
2204+ }
2205+ else {
2206+ minorVersion = CA_UKN_MINOR_VERSION;
2207+ }
2208+
2209+ /*
2210+ * the type field is abused to carry the port number
2211+ * so that we can have multiple servers on one host
2212+ */
2213+ osiSockAddr serverAddr;
2214+ serverAddr.ia.sin_family = AF_INET;
2215+ if ( CA_V48 ( minorVersion ) ) {
2216+ if ( msg.m_cid != INADDR_BROADCAST ) {
2217+ serverAddr.ia.sin_addr.s_addr = htonl ( msg.m_cid );
2218+ }
2219+ else {
2220+ serverAddr.ia.sin_addr = addr.ia.sin_addr;
2221+ }
2222+ serverAddr.ia.sin_port = htons ( msg.m_dataType );
2223+ }
2224+ else if ( CA_V45 (minorVersion) ) {
2225+ serverAddr.ia.sin_port = htons ( msg.m_dataType );
2226+ serverAddr.ia.sin_addr = addr.ia.sin_addr;
2227+ }
2228+ else {
2229+ serverAddr.ia.sin_port = htons ( _udpiiu.serverPort );
2230+ serverAddr.ia.sin_addr = addr.ia.sin_addr;
2231+ }
2232+
2233+ if ( CA_V42 ( minorVersion ) ) {
2234+ _udpiiu.cacRef.transferChanToVirtCircuit
2235+ ( msg.m_available, msg.m_cid, 0xffff,
2236+ 0, minorVersion, serverAddr, currentTime );
2237+ }
2238+ else {
2239+ _udpiiu.cacRef.transferChanToVirtCircuit
2240+ ( msg.m_available, msg.m_cid, msg.m_dataType,
2241+ msg.m_count, minorVersion, serverAddr, currentTime );
2242+ }
2243+}
2244+
2245+void udpiiu :: SearchRespCallback :: show (
2246+ epicsGuard < epicsMutex > & guard, unsigned level ) const
2247+{
2248+ guard.assertIdenticalMutex ( _udpiiu.cacMutex );
2249+ ::printf ( "udpiiu :: SearchRespCallback\n" );
2250+}
2251+
2252+bool udpiiu :: datagramFlush (
2253+ epicsGuard < epicsMutex > & guard, const epicsTime & currentTime )
2254+{
2255+ guard.assertIdenticalMutex ( cacMutex );
2256+
2257 // dont send the version header by itself
2258 if ( this->nBytesInXmitBuf <= sizeof ( caHdr ) ) {
2259 return false;
2260 }
2261
2262- osiSockAddrNode *pNode = ( osiSockAddrNode * ) // X aCC 749
2263- ellFirst ( & this->dest );
2264- while ( pNode ) {
2265- int status;
2266-
2267- assert ( this->nBytesInXmitBuf <= INT_MAX );
2268- status = sendto ( this->sock, this->xmitBuf,
2269- (int) this->nBytesInXmitBuf, 0,
2270- &pNode->addr.sa, sizeof ( pNode->addr.sa ) );
2271- if ( status != (int) this->nBytesInXmitBuf ) {
2272- if ( status >= 0 ) {
2273- errlogPrintf ( "CAC: UDP sendto () call returned strange xmit count?\n" );
2274- break;
2275- }
2276- else {
2277- int localErrno = SOCKERRNO;
2278-
2279- if ( localErrno == SOCK_EINTR ) {
2280- if ( this->shutdownCmd ) {
2281- break;
2282- }
2283- else {
2284- continue;
2285- }
2286- }
2287- else if ( localErrno == SOCK_SHUTDOWN ) {
2288- break;
2289- }
2290- else if ( localErrno == SOCK_ENOTSOCK ) {
2291- break;
2292- }
2293- else if ( localErrno == SOCK_EBADF ) {
2294- break;
2295- }
2296- else {
2297- char sockErrBuf[64];
2298- epicsSocketConvertErrnoToString (
2299- sockErrBuf, sizeof ( sockErrBuf ) );
2300- char buf[64];
2301- sockAddrToDottedIP ( &pNode->addr.sa, buf, sizeof ( buf ) );
2302- errlogPrintf (
2303- "CAC: error = \"%s\" sending UDP msg to %s\n",
2304- sockErrBuf, buf);
2305- break;
2306- }
2307- }
2308- }
2309- pNode = (osiSockAddrNode *) ellNext ( &pNode->node ); // X aCC 749
2310+ tsDLIter < SearchDest > iter ( _searchDestList.firstIter () );
2311+ while ( iter.valid () )
2312+ {
2313+ iter->searchRequest ( guard, this->xmitBuf, this->nBytesInXmitBuf );
2314+ iter++;
2315 }
2316
2317 this->nBytesInXmitBuf = 0u;
2318@@ -960,7 +1078,7 @@
2319 return true;
2320 }
2321
2322-void udpiiu::show ( unsigned level ) const
2323+void udpiiu :: show ( unsigned level ) const
2324 {
2325 epicsGuard < epicsMutex > guard ( this->cacMutex );
2326
2327@@ -968,7 +1086,17 @@
2328 if ( level > 1u ) {
2329 ::printf ("\trepeater port %u\n", this->repeaterPort );
2330 ::printf ("\tdefault server port %u\n", this->serverPort );
2331- printChannelAccessAddressList ( & this->dest );
2332+ ::printf ( "Search Destination List with %u items\n",
2333+ _searchDestList.count () );
2334+ if ( level > 2u ) {
2335+ tsDLIterConst < SearchDest > iter (
2336+ _searchDestList.firstIter () );
2337+ while ( iter.valid () )
2338+ {
2339+ iter->show ( guard, level - 2 );
2340+ iter++;
2341+ }
2342+ }
2343 }
2344 if ( level > 2u ) {
2345 ::printf ("\tsocket identifier %d\n", this->sock );
2346
2347=== modified file 'src/ca/udpiiu.h'
2348--- src/ca/udpiiu.h 2007-08-23 17:46:28 +0000
2349+++ src/ca/udpiiu.h 2010-05-14 13:38:34 +0000
2350@@ -1,11 +1,11 @@
2351 /*************************************************************************\
2352-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
2353-* National Laboratory.
2354-* Copyright (c) 2002 The Regents of the University of California, as
2355-* Operator of Los Alamos National Laboratory.
2356-* EPICS BASE Versions 3.13.7
2357-* and higher are distributed subject to a Software License Agreement found
2358-* in file LICENSE that is included with this distribution.
2359+ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
2360+ * National Laboratory.
2361+ * Copyright (c) 2002 The Regents of the University of California, as
2362+ * Operator of Los Alamos National Laboratory.
2363+ * EPICS BASE Versions 3.13.7
2364+ * and higher are distributed subject to a Software License Agreement found
2365+ * in file LICENSE that is included with this distribution.
2366 \*************************************************************************/
2367
2368 /*
2369@@ -47,6 +47,7 @@
2370 #include "searchTimer.h"
2371 #include "disconnectGovernorTimer.h"
2372 #include "repeaterSubscribeTimer.h"
2373+#include "SearchDest.h"
2374
2375 extern "C" void cacRecvThreadUDP ( void *pParam );
2376
2377@@ -97,7 +98,9 @@
2378 epicsMutex & callbackControl,
2379 epicsMutex & mutualExclusion,
2380 cacContextNotify &,
2381- class cac & );
2382+ class cac &,
2383+ unsigned port,
2384+ tsDLList < SearchDest > & );
2385 virtual ~udpiiu ();
2386 void installNewChannel (
2387 epicsGuard < epicsMutex > &, nciu &, netiiu * & );
2388@@ -108,17 +111,41 @@
2389 void shutdown ( epicsGuard < epicsMutex > & cbGuard,
2390 epicsGuard < epicsMutex > & guard );
2391 void show ( unsigned level ) const;
2392-
2393+
2394 // exceptions
2395 class noSocket {};
2396
2397 private:
2398+ class SearchDestUDP :
2399+ public SearchDest {
2400+ public:
2401+ SearchDestUDP ( const osiSockAddr &, udpiiu & );
2402+ void searchRequest (
2403+ epicsGuard < epicsMutex > &, const char * pBuf, size_t bufLen );
2404+ void show (
2405+ epicsGuard < epicsMutex > &, unsigned level ) const;
2406+ private:
2407+ osiSockAddr _destAddr;
2408+ udpiiu & _udpiiu;
2409+ };
2410+ class SearchRespCallback :
2411+ public SearchDest :: Callback {
2412+ public:
2413+ SearchRespCallback ( udpiiu & );
2414+ void notify (
2415+ const caHdr &, const void * pPayload,
2416+ const osiSockAddr &, const epicsTime & );
2417+ void show (
2418+ epicsGuard < epicsMutex > &, unsigned level ) const;
2419+ private:
2420+ udpiiu & _udpiiu;
2421+ };
2422 char xmitBuf [MAX_UDP_SEND];
2423 char recvBuf [MAX_UDP_RECV];
2424 udpRecvThread recvThread;
2425 repeaterSubscribeTimer repeaterSubscribeTmr;
2426 disconnectGovernorTimer govTmr;
2427- ELLLIST dest;
2428+ tsDLList < SearchDest > _searchDestList;
2429 double maxPeriod;
2430 double rtteMean;
2431 double rtteMeanDev;
2432
2433=== modified file 'src/ca/virtualCircuit.h'
2434--- src/ca/virtualCircuit.h 2009-07-14 22:39:41 +0000
2435+++ src/ca/virtualCircuit.h 2010-05-14 13:38:34 +0000
2436@@ -1,12 +1,13 @@
2437 /*************************************************************************\
2438-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
2439-* National Laboratory.
2440-* Copyright (c) 2002 The Regents of the University of California, as
2441-* Operator of Los Alamos National Laboratory.
2442-* EPICS BASE Versions 3.13.7
2443-* and higher are distributed subject to a Software License Agreement found
2444-* in file LICENSE that is included with this distribution.
2445+ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
2446+ * National Laboratory.
2447+ * Copyright (c) 2002 The Regents of the University of California, as
2448+ * Operator of Los Alamos National Laboratory.
2449+ * EPICS BASE Versions 3.13.7
2450+ * and higher are distributed subject to a Software License Agreement found
2451+ * in file LICENSE that is included with this distribution.
2452 \*************************************************************************/
2453+
2454 /*
2455 *
2456 *
2457@@ -37,6 +38,7 @@
2458 #include "tcpRecvWatchdog.h"
2459 #include "tcpSendWatchdog.h"
2460 #include "hostNameCache.h"
2461+#include "SearchDest.h"
2462 #include "compilerDependencies.h"
2463
2464 class callbackManager;
2465@@ -93,15 +95,34 @@
2466 void run ();
2467 };
2468
2469-class tcpiiu :
2470+class SearchDestTCP : public SearchDest {
2471+public:
2472+ SearchDestTCP ( cac &, const osiSockAddr & );
2473+ void searchRequest ( epicsGuard < epicsMutex > & guard,
2474+ const char * pbuf, size_t len );
2475+ void show ( epicsGuard < epicsMutex > & guard, unsigned level ) const;
2476+ void setCircuit ( tcpiiu * );
2477+ void disable ();
2478+ void enable ();
2479+private:
2480+ tcpiiu * _ptcpiiu;
2481+ cac & _cac;
2482+ const osiSockAddr _addr;
2483+ bool _active;
2484+};
2485+
2486+class tcpiiu :
2487 public netiiu, public tsDLNode < tcpiiu >,
2488 public tsSLNode < tcpiiu >, public caServerID,
2489 private wireSendAdapter, private wireRecvAdapter {
2490+ friend void SearchDestTCP::searchRequest ( epicsGuard < epicsMutex > & guard,
2491+ const char * pbuf, size_t len );
2492 public:
2493 tcpiiu ( cac & cac, epicsMutex & mutualExclusion, epicsMutex & callbackControl,
2494 cacContextNotify &, double connectionTimeout, epicsTimerQueue & timerQueue,
2495 const osiSockAddr & addrIn, comBufMemoryManager &, unsigned minorVersion,
2496- ipAddrToAsciiEngine & engineIn, const cacChannel::priLev & priorityIn );
2497+ ipAddrToAsciiEngine & engineIn, const cacChannel::priLev & priorityIn,
2498+ SearchDestTCP * pSearchDestIn = NULL);
2499 ~tcpiiu ();
2500 void start (
2501 epicsGuard < epicsMutex > & );
2502@@ -175,12 +196,15 @@
2503 epicsGuard < epicsMutex > & guard, nciu & chan );
2504 bool connectNotify (
2505 epicsGuard < epicsMutex > &, nciu & chan );
2506- void nameResolutionMsgEndNotify ();
2507+
2508+ void searchRespNotify (
2509+ const epicsTime &, const caHdrLargeArray & );
2510+ void versionRespNotify ( const caHdrLargeArray & );
2511
2512 void * operator new ( size_t size,
2513 tsFreeList < class tcpiiu, 32, epicsMutexNOOP > & );
2514- epicsPlacementDeleteOperator (( void *,
2515- tsFreeList < class tcpiiu, 32, epicsMutexNOOP > & ))
2516+ epicsPlacementDeleteOperator (( void *,
2517+ tsFreeList < class tcpiiu, 32, epicsMutexNOOP > & ));
2518
2519 private:
2520 hostNameCache hostNameCacheInstance;
2521@@ -205,6 +229,7 @@
2522 comBufMemoryManager & comBufMemMgr;
2523 cac & cacRef;
2524 char * pCurData;
2525+ SearchDestTCP * pSearchDest;
2526 epicsMutex & mutex;
2527 epicsMutex & cbMutex;
2528 unsigned minorProtocolVersion;
2529@@ -257,6 +282,7 @@
2530 bool bytesArePendingInOS () const;
2531 void decrementBlockingForFlushCount (
2532 epicsGuard < epicsMutex > & guard );
2533+ bool isNameService () const;
2534
2535 // send protocol stubs
2536 void echoRequest (
2537@@ -386,5 +412,14 @@
2538 this->recvDog.probeResponseNotify ( cbGuard );
2539 }
2540
2541+inline bool tcpiiu::isNameService () const
2542+{
2543+ return ( this->pSearchDest != NULL );
2544+}
2545+
2546+inline void SearchDestTCP::setCircuit ( tcpiiu * piiu )
2547+{
2548+ _ptcpiiu = piiu;
2549+}
2550+
2551 #endif // ifdef virtualCircuith
2552-
2553
2554=== modified file 'src/cas/generic/caHdrLargeArray.h'
2555--- src/cas/generic/caHdrLargeArray.h 2003-02-12 19:11:43 +0000
2556+++ src/cas/generic/caHdrLargeArray.h 2010-05-14 13:38:34 +0000
2557@@ -32,7 +32,7 @@
2558 # include "shareLib.h"
2559 #endif
2560
2561-static const unsigned char CA_MINOR_PROTOCOL_REVISION = 11;
2562+static const unsigned char CA_MINOR_PROTOCOL_REVISION = 12;
2563
2564 typedef ca_uint32_t caResId;
2565
2566
2567=== modified file 'src/cas/generic/casStrmClient.cc'
2568--- src/cas/generic/casStrmClient.cc 2009-08-18 00:36:22 +0000
2569+++ src/cas/generic/casStrmClient.cc 2010-05-14 13:38:34 +0000
2570@@ -1,29 +1,27 @@
2571 /*************************************************************************\
2572-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
2573-* National Laboratory.
2574-* Copyright (c) 2002 The Regents of the University of California, as
2575-* Operator of Los Alamos National Laboratory.
2576-* EPICS BASE Versions 3.13.7
2577-* and higher are distributed subject to a Software License Agreement found
2578-* in file LICENSE that is included with this distribution.
2579+ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
2580+ * National Laboratory.
2581+ * Copyright (c) 2002 The Regents of the University of California, as
2582+ * Operator of Los Alamos National Laboratory.
2583+ * EPICS BASE Versions 3.13.7
2584+ * and higher are distributed subject to a Software License Agreement found
2585+ * in file LICENSE that is included with this distribution.
2586 \*************************************************************************/
2587+
2588 /*
2589- * $Id$
2590- *
2591 * Author Jeffrey O. Hill
2592- * johill@lanl.gov
2593- * 505 665 1831
2594 */
2595
2596 // *must* be defined before including net_convert.h
2597 typedef unsigned long arrayElementCount;
2598
2599 #include "osiWireFormat.h"
2600-#include "net_convert.h" // byte order conversion from libca
2601-#include "dbMapper.h" // ait to dbr types
2602+#include "net_convert.h" // byte order conversion from libca
2603+#include "dbMapper.h" // ait to dbr types
2604 #include "gddAppTable.h" // EPICS application type table
2605-#include "gddApps.h" // gdd predefined application type codes
2606+#include "gddApps.h" // gdd predefined application type codes
2607 #include "errlog.h"
2608+#include "osiPoolStatus.h" // is there sufficent space in pool
2609
2610 #define epicsExportSharedSymbols
2611 #include "casStrmClient.h"
2612@@ -47,7 +45,7 @@
2613 & casStrmClient::readAction,
2614 & casStrmClient::writeAction,
2615 & casStrmClient::uknownMessageAction,
2616- & casStrmClient::uknownMessageAction,
2617+ & casStrmClient::searchAction,
2618 & casStrmClient::uknownMessageAction,
2619 & casStrmClient::eventsOffAction,
2620 & casStrmClient::eventsOnAction,
2621@@ -74,10 +72,13 @@
2622 //
2623 // casStrmClient::casStrmClient()
2624 //
2625-casStrmClient::casStrmClient ( caServerI & cas, clientBufMemoryManager & mgrIn ) :
2626+casStrmClient::casStrmClient (
2627+ caServerI & cas, clientBufMemoryManager & mgrIn,
2628+ const caNetAddr & clientAddr ) :
2629 casCoreClient ( cas ),
2630 in ( *this, mgrIn, 1 ),
2631 out ( *this, mgrIn ),
2632+ _clientAddr ( clientAddr ),
2633 pUserName ( 0 ),
2634 pHostName ( 0 ),
2635 incommingBytesToDrain ( 0 ),
2636@@ -141,7 +142,7 @@
2637 this->incommingBytesToDrain = 0u;
2638 }
2639 }
2640-
2641+
2642 //
2643 // process any messages in the in buffer
2644 //
2645@@ -618,30 +619,30 @@
2646 }
2647
2648 {
2649- caStatus servStat = this->read ();
2650- if ( servStat == S_casApp_success ) {
2651+ caStatus servStat = this->read ();
2652+ if ( servStat == S_casApp_success ) {
2653 assert ( pValueRead.valid () );
2654 caStatus status = this->readNotifyResponse (
2655 guard, pChan, *mp,
2656 *pValueRead, servStat );
2657 this->responseIsPending = ( status != S_cas_success );
2658 return status;
2659- }
2660- else if ( servStat == S_casApp_asyncCompletion ) {
2661- return S_cas_success;
2662- }
2663- else if ( servStat == S_casApp_postponeAsyncIO ) {
2664+ }
2665+ else if ( servStat == S_casApp_asyncCompletion ) {
2666+ return S_cas_success;
2667+ }
2668+ else if ( servStat == S_casApp_postponeAsyncIO ) {
2669 return S_casApp_postponeAsyncIO;
2670- }
2671- else {
2672- caStatus status = this->readNotifyFailureResponse (
2673- guard, *mp, ECA_GETFAIL );
2674+ }
2675+ else {
2676+ caStatus status = this->readNotifyFailureResponse (
2677+ guard, *mp, ECA_GETFAIL );
2678 if ( status != S_cas_success ) {
2679 this->pendingResponseStatus = servStat;
2680- this->responseIsPending = true;
2681- }
2682+ this->responseIsPending = true;
2683+ }
2684 return status;
2685- }
2686+ }
2687 }
2688 }
2689
2690@@ -1025,23 +1026,23 @@
2691 //
2692 {
2693 caStatus servStat = this->write ( & casChannelI :: write );
2694- if ( servStat == S_casApp_success ||
2695+ if ( servStat == S_casApp_success ||
2696 servStat == S_casApp_asyncCompletion ) {
2697 return S_cas_success;
2698- }
2699- else if ( servStat == S_casApp_postponeAsyncIO ) {
2700+ }
2701+ else if ( servStat == S_casApp_postponeAsyncIO ) {
2702 return S_casApp_postponeAsyncIO;
2703- }
2704- else {
2705+ }
2706+ else {
2707 caStatus status =
2708 this->writeActionSendFailureStatus ( guard, *mp,
2709 pChan->getCID(), servStat );
2710 if ( status != S_cas_success ) {
2711 this->pendingResponseStatus = servStat;
2712 this->responseIsPending = true;
2713- }
2714+ }
2715 return status;
2716- }
2717+ }
2718 }
2719
2720 //
2721@@ -1194,6 +1195,221 @@
2722 return status;
2723 }
2724
2725+//
2726+// casStrmClient :: asyncSearchResp()
2727+//
2728+caStatus casStrmClient :: asyncSearchResponse (
2729+ epicsGuard < casClientMutex > & guard, const caNetAddr & /* outAddr */,
2730+ const caHdrLargeArray & msg, const pvExistReturn & retVal,
2731+ ca_uint16_t /* protocolRevision */, ca_uint32_t /* sequenceNumber */ )
2732+{
2733+ return this->searchResponse ( guard, msg, retVal );
2734+}
2735+
2736+// casStrmClient :: hostName()
2737+void casStrmClient :: hostName ( char * pInBuf, unsigned bufSizeIn ) const
2738+{
2739+ _clientAddr.stringConvert ( pInBuf, bufSizeIn );
2740+}
2741+
2742+//
2743+// caStatus casStrmClient :: searchResponse()
2744+//
2745+caStatus casStrmClient :: searchResponse (
2746+ epicsGuard < casClientMutex > & guard,
2747+ const caHdrLargeArray & msg,
2748+ const pvExistReturn & retVal )
2749+{
2750+ if ( retVal.getStatus() != pverExistsHere ) {
2751+ return S_cas_success;
2752+ }
2753+
2754+ //
2755+ // starting with V4.1 the count field is used (abused)
2756+ // by the client to store the minor version number of
2757+ // the client.
2758+ //
2759+ // Old versions expect alloc of channel in response
2760+ // to a search request. This is no longer supported.
2761+ //
2762+ if ( !CA_V44( msg.m_count ) ) {
2763+ errlogPrintf (
2764+ "client \"%s\" using EPICS R3.11 CA "
2765+ "connect protocol was ignored\n",
2766+ pHostName );
2767+ //
2768+ // old connect protocol was dropped when the
2769+ // new API was added to the server (they must
2770+ // now use clients at EPICS 3.12 or higher)
2771+ //
2772+ caStatus status = this->sendErr (
2773+ guard, & msg, invalidResID, ECA_DEFUNCT,
2774+ "R3.11 connect sequence from old client was ignored" );
2775+ return status;
2776+ }
2777+
2778+ //
2779+ // cid field is abused to carry the IP
2780+ // address in CA_V48 or higher
2781+ // (this allows a CA servers to serve
2782+ // as a directory service)
2783+ //
2784+ // data type field is abused to carry the IP
2785+ // port number here CA_V44 or higher
2786+ // (this allows multiple CA servers on one
2787+ // host)
2788+ //
2789+ ca_uint32_t serverAddr;
2790+ ca_uint16_t serverPort;
2791+ if ( CA_V48( msg.m_count ) ) {
2792+ struct sockaddr_in ina;
2793+ if ( retVal.addrIsValid() ) {
2794+ caNetAddr addr = retVal.getAddr();
2795+ ina = addr.getSockIP();
2796+ //
2797+ // If they dont specify a port number then the default
2798+ // CA server port is assumed when it it is a server
2799+ // address redirect (it is never correct to use this
2800+ // server's port when it is a redirect).
2801+ //
2802+ if ( ina.sin_port == 0u ) {
2803+ ina.sin_port = htons ( CA_SERVER_PORT );
2804+ }
2805+ }
2806+ else {
2807+ //
2808+ // We dont fill in the servers address here because
2809+ // the client has a tcp circuit to us and he knows
2810+ // our address
2811+ //
2812+ ina.sin_addr.s_addr = htonl ( ~0U );
2813+ ina.sin_port = htons ( 0 );
2814+ }
2815+ serverAddr = ntohl ( ina.sin_addr.s_addr );
2816+ serverPort = ntohs ( ina.sin_port );
2817+ }
2818+ else {
2819+ serverAddr = ntohl ( ~0U );
2820+ serverPort = ntohs ( 0 );
2821+ }
2822+
2823+ caStatus status = this->out.copyInHeader ( CA_PROTO_SEARCH,
2824+ 0, serverPort, 0, serverAddr, msg.m_available, 0 );
2825+ //
2826+ // Starting with CA V4.1 the minor version number
2827+ // is appended to the end of each search reply.
2828+ // This value is ignored by earlier clients.
2829+ //
2830+ if ( status == S_cas_success ) {
2831+ this->out.commitMsg ();
2832+ }
2833+
2834+ return status;
2835+}
2836+
2837+//
2838+// casStrmClient :: searchAction()
2839+//
2840+caStatus casStrmClient :: searchAction ( epicsGuard < casClientMutex > & guard )
2841+{
2842+ const caHdrLargeArray *mp = this->ctx.getMsg();
2843+ const char *pChanName = static_cast <char * > ( this->ctx.getData() );
2844+ caStatus status;
2845+
2846+ //
2847+ // check the sanity of the message
2848+ //
2849+ if ( mp->m_postsize <= 1 ) {
2850+ caServerI::dumpMsg ( this->pHostName, "?", mp, this->ctx.getData(),
2851+ "empty PV name extension in TCP search request?\n" );
2852+ return S_cas_success;
2853+ }
2854+
2855+ if ( pChanName[0] == '\0' ) {
2856+ caServerI::dumpMsg ( this->pHostName, "?", mp, this->ctx.getData(),
2857+ "zero length PV name in UDP search request?\n" );
2858+ return S_cas_success;
2859+ }
2860+
2861+ // check for an unterminated string before calling server tool
2862+ // by searching backwards through the string (some early versions
2863+ // of the client library might not be setting the pad bytes to nill)
2864+ for ( unsigned i = mp->m_postsize-1; pChanName[i] != '\0'; i-- ) {
2865+ if ( i <= 1 ) {
2866+ caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
2867+ "unterminated PV name in UDP search request?\n" );
2868+ return S_cas_success;
2869+ }
2870+ }
2871+
2872+ if ( this->getCAS().getDebugLevel() > 6u ) {
2873+ this->hostName ( this->pHostName, sizeof ( pHostName ) );
2874+ printf ( "\"%s\" is searching for \"%s\"\n",
2875+ pHostName, pChanName );
2876+ }
2877+
2878+ //
2879+ // verify that we have sufficent memory for a PV and a
2880+ // monitor prior to calling PV exist test so that when
2881+ // the server runs out of memory we dont reply to
2882+ // search requests, and therefore dont thrash through
2883+ // caServer::pvExistTest() and casCreatePV::pvAttach()
2884+ //
2885+ if ( ! osiSufficentSpaceInPool ( 0 ) ) {
2886+ return S_cas_success;
2887+ }
2888+
2889+ //
2890+ // ask the server tool if this PV exists
2891+ //
2892+ this->userStartedAsyncIO = false;
2893+ pvExistReturn pver =
2894+ this->getCAS()->pvExistTest (
2895+ this->ctx, _clientAddr, pChanName );
2896+
2897+ //
2898+ // prevent problems when they initiate
2899+ // async IO but dont return status
2900+ // indicating so (and vise versa)
2901+ //
2902+ if ( this->userStartedAsyncIO ) {
2903+ if ( pver.getStatus() != pverAsyncCompletion ) {
2904+ errMessage ( S_cas_badParameter,
2905+ "- assuming asynch IO status from caServer::pvExistTest()");
2906+ }
2907+ status = S_cas_success;
2908+ }
2909+ else {
2910+ //
2911+ // otherwise we assume sync IO operation was initiated
2912+ //
2913+ switch ( pver.getStatus() ) {
2914+ case pverExistsHere:
2915+ status = this->searchResponse ( guard, *mp, pver );
2916+ break;
2917+
2918+ case pverDoesNotExistHere:
2919+ status = S_cas_success;
2920+ break;
2921+
2922+ case pverAsyncCompletion:
2923+ errMessage ( S_cas_badParameter,
2924+ "- unexpected asynch IO status from "
2925+ "caServer::pvExistTest() ignored");
2926+ status = S_cas_success;
2927+ break;
2928+
2929+ default:
2930+ errMessage ( S_cas_badParameter,
2931+ "- invalid return from "
2932+ "caServer::pvExistTest() ignored");
2933+ status = S_cas_success;
2934+ break;
2935+ }
2936+ }
2937+ return status;
2938+}
2939+
2940 /*
2941 * casStrmClient::hostNameAction()
2942 */
2943@@ -2610,9 +2826,8 @@
2944 epicsGuard < epicsMutex > guard ( this->mutex );
2945 return this->in.fill ();
2946 }
2947-
2948-bufSizeT casStrmClient ::
2949- inBufBytesPending () const
2950+
2951+bufSizeT casStrmClient :: inBufBytesPending () const
2952 {
2953 epicsGuard < epicsMutex > guard ( this->mutex );
2954 return this->in.bytesPresent ();
2955
2956=== modified file 'src/cas/generic/casStrmClient.h'
2957--- src/cas/generic/casStrmClient.h 2009-08-05 23:58:40 +0000
2958+++ src/cas/generic/casStrmClient.h 2010-05-14 13:38:34 +0000
2959@@ -1,12 +1,11 @@
2960-
2961 /*************************************************************************\
2962-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
2963-* National Laboratory.
2964-* Copyright (c) 2002 The Regents of the University of California, as
2965-* Operator of Los Alamos National Laboratory.
2966-* EPICS BASE Versions 3.13.7
2967-* and higher are distributed subject to a Software License Agreement found
2968-* in file LICENSE that is included with this distribution.
2969+ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
2970+ * National Laboratory.
2971+ * Copyright (c) 2002 The Regents of the University of California, as
2972+ * Operator of Los Alamos National Laboratory.
2973+ * EPICS BASE Versions 3.13.7
2974+ * and higher are distributed subject to a Software License Agreement found
2975+ * in file LICENSE that is included with this distribution.
2976 \*************************************************************************/
2977
2978 #ifndef casStrmClienth
2979@@ -37,43 +36,44 @@
2980 public casCoreClient, public outBufClient,
2981 public inBufClient, public tsDLNode < casStrmClient > {
2982 public:
2983- casStrmClient ( caServerI &, clientBufMemoryManager & );
2984- virtual ~casStrmClient();
2985- void show ( unsigned level ) const;
2986+ casStrmClient ( caServerI &, clientBufMemoryManager &, const caNetAddr & clientAddr );
2987+ virtual ~casStrmClient();
2988+ void show ( unsigned level ) const;
2989 outBufClient::flushCondition flush ();
2990- unsigned getDebugLevel () const;
2991- virtual void hostName ( char * pBuf, unsigned bufSize ) const = 0;
2992- void userName ( char * pBuf, unsigned bufSize ) const;
2993- ca_uint16_t protocolRevision () const;
2994+ unsigned getDebugLevel () const;
2995+ void hostName ( char * pBuf, unsigned bufSize ) const;
2996+ void userName ( char * pBuf, unsigned bufSize ) const;
2997+ ca_uint16_t protocolRevision () const;
2998 void sendVersion ();
2999 protected:
3000- caStatus processMsg ();
3001+ caStatus processMsg ();
3002 bool inBufFull () const;
3003 inBufClient::fillCondition inBufFill ();
3004 bufSizeT inBufBytesPending () const;
3005 bufSizeT outBufBytesPending () const;
3006 private:
3007- char hostNameStr [32];
3008+ //char hostNameStr [32];
3009 inBuf in;
3010 outBuf out;
3011- chronIntIdResTable < casChannelI > chanTable;
3012- tsDLList < casChannelI > chanList;
3013- epicsTime lastSendTS;
3014- epicsTime lastRecvTS;
3015- char * pUserName;
3016- char * pHostName;
3017+ chronIntIdResTable < casChannelI > chanTable;
3018+ tsDLList < casChannelI > chanList;
3019+ epicsTime lastSendTS;
3020+ epicsTime lastRecvTS;
3021+ caNetAddr _clientAddr;
3022+ char * pUserName;
3023+ char * pHostName;
3024 smartGDDPointer pValueRead;
3025 unsigned incommingBytesToDrain;
3026 caStatus pendingResponseStatus;
3027- ca_uint16_t minor_version_number;
3028+ ca_uint16_t minor_version_number;
3029 bool reqPayloadNeedsByteSwap;
3030 bool responseIsPending;
3031
3032- caStatus createChannel ( const char * pName );
3033- caStatus verifyRequest ( casChannelI * & pChan );
3034+ caStatus createChannel ( const char * pName );
3035+ caStatus verifyRequest ( casChannelI * & pChan );
3036 typedef caStatus ( casStrmClient :: * pCASMsgHandler )
3037- ( epicsGuard < casClientMutex > & );
3038- static pCASMsgHandler const msgHandlers[CA_PROTO_LAST_CMMD+1u];
3039+ ( epicsGuard < casClientMutex > & );
3040+ static pCASMsgHandler const msgHandlers[CA_PROTO_LAST_CMMD+1u];
3041
3042 //
3043 // one function for each CA request type
3044@@ -82,19 +82,20 @@
3045 caStatus ignoreMsgAction ( epicsGuard < casClientMutex > & );
3046 caStatus versionAction ( epicsGuard < casClientMutex > & );
3047 caStatus echoAction ( epicsGuard < casClientMutex > & );
3048- caStatus eventAddAction ( epicsGuard < casClientMutex > & );
3049- caStatus eventCancelAction ( epicsGuard < casClientMutex > & );
3050- caStatus readAction ( epicsGuard < casClientMutex > & );
3051- caStatus readNotifyAction ( epicsGuard < casClientMutex > & );
3052- caStatus writeAction ( epicsGuard < casClientMutex > & );
3053- caStatus eventsOffAction ( epicsGuard < casClientMutex > & );
3054- caStatus eventsOnAction ( epicsGuard < casClientMutex > & );
3055- caStatus readSyncAction ( epicsGuard < casClientMutex > & );
3056- caStatus clearChannelAction ( epicsGuard < casClientMutex > & );
3057- caStatus claimChannelAction ( epicsGuard < casClientMutex > & );
3058- caStatus writeNotifyAction ( epicsGuard < casClientMutex > & );
3059- caStatus clientNameAction ( epicsGuard < casClientMutex > & );
3060- caStatus hostNameAction ( epicsGuard < casClientMutex > & );
3061+ caStatus eventAddAction ( epicsGuard < casClientMutex > & );
3062+ caStatus eventCancelAction ( epicsGuard < casClientMutex > & );
3063+ caStatus readAction ( epicsGuard < casClientMutex > & );
3064+ caStatus readNotifyAction ( epicsGuard < casClientMutex > & );
3065+ caStatus writeAction ( epicsGuard < casClientMutex > & );
3066+ caStatus eventsOffAction ( epicsGuard < casClientMutex > & );
3067+ caStatus eventsOnAction ( epicsGuard < casClientMutex > & );
3068+ caStatus readSyncAction ( epicsGuard < casClientMutex > & );
3069+ caStatus clearChannelAction ( epicsGuard < casClientMutex > & );
3070+ caStatus claimChannelAction ( epicsGuard < casClientMutex > & );
3071+ caStatus writeNotifyAction ( epicsGuard < casClientMutex > & );
3072+ caStatus clientNameAction ( epicsGuard < casClientMutex > & );
3073+ caStatus hostNameAction ( epicsGuard < casClientMutex > & );
3074+ caStatus searchAction ( epicsGuard < casClientMutex > & );
3075 caStatus sendErr ( epicsGuard < casClientMutex > &,
3076 const caHdrLargeArray *curp, ca_uint32_t cid,
3077 const int reportedStatus, const char * pformat, ... );
3078@@ -114,34 +115,40 @@
3079 // one function for each CA request type that has
3080 // asynchronous completion
3081 //
3082- caStatus createChanResponse ( epicsGuard < casClientMutex > &,
3083- casCtx &, const pvAttachReturn & );
3084- caStatus readResponse ( epicsGuard < casClientMutex > &,
3085- casChannelI * pChan, const caHdrLargeArray & msg,
3086- const gdd & desc, const caStatus status );
3087- caStatus readNotifyResponse ( epicsGuard < casClientMutex > &,
3088+ caStatus createChanResponse ( epicsGuard < casClientMutex > &,
3089+ casCtx &, const pvAttachReturn & );
3090+ caStatus readResponse ( epicsGuard < casClientMutex > &,
3091+ casChannelI * pChan, const caHdrLargeArray & msg,
3092+ const gdd & desc, const caStatus status );
3093+ caStatus readNotifyResponse ( epicsGuard < casClientMutex > &,
3094 casChannelI *pChan, const caHdrLargeArray & msg,
3095- const gdd & desc, const caStatus status );
3096- caStatus writeResponse ( epicsGuard < casClientMutex > &, casChannelI &,
3097- const caHdrLargeArray & msg, const caStatus status );
3098- caStatus writeNotifyResponse ( epicsGuard < casClientMutex > &, casChannelI &,
3099- const caHdrLargeArray &, const caStatus status );
3100- caStatus monitorResponse ( epicsGuard < casClientMutex > &,
3101+ const gdd & desc, const caStatus status );
3102+ caStatus writeResponse ( epicsGuard < casClientMutex > &, casChannelI &,
3103+ const caHdrLargeArray & msg, const caStatus status );
3104+ caStatus writeNotifyResponse ( epicsGuard < casClientMutex > &, casChannelI &,
3105+ const caHdrLargeArray &, const caStatus status );
3106+ caStatus monitorResponse ( epicsGuard < casClientMutex > &,
3107 casChannelI & chan, const caHdrLargeArray & msg,
3108- const gdd &, const caStatus status );
3109+ const gdd & desc, const caStatus status );
3110 caStatus enumPostponedCreateChanResponse ( epicsGuard < casClientMutex > &,
3111 casChannelI & chan, const caHdrLargeArray & hdr );
3112 caStatus privateCreateChanResponse ( epicsGuard < casClientMutex > &,
3113 casChannelI & chan, const caHdrLargeArray & hdr, unsigned dbrType );
3114- caStatus channelCreateFailedResp ( epicsGuard < casClientMutex > &,
3115+ caStatus channelCreateFailedResp ( epicsGuard < casClientMutex > &,
3116 const caHdrLargeArray &, const caStatus createStatus );
3117 caStatus channelDestroyEventNotify (
3118 epicsGuard < casClientMutex > & guard,
3119 casChannelI * const pChan, ca_uint32_t sid );
3120- caStatus accessRightsResponse (
3121+ caStatus accessRightsResponse (
3122 casChannelI * pciu );
3123- caStatus accessRightsResponse (
3124+ caStatus accessRightsResponse (
3125 epicsGuard < casClientMutex > &, casChannelI * pciu );
3126+ caStatus searchResponse (
3127+ epicsGuard < casClientMutex > &, const caHdrLargeArray &, const pvExistReturn & );
3128+ caStatus asyncSearchResponse (
3129+ epicsGuard < casClientMutex > &, const caNetAddr & outAddr,
3130+ const caHdrLargeArray & msg, const pvExistReturn & retVal,
3131+ ca_uint16_t protocolRevision, ca_uint32_t sequenceNumber );
3132
3133
3134 typedef caStatus ( casChannelI :: * PWriteMethod ) (
3135@@ -152,29 +159,29 @@
3136 caStatus writeScalarData( PWriteMethod );
3137
3138 outBufClient::flushCondition xSend ( char * pBuf, bufSizeT nBytesToSend,
3139- bufSizeT & nBytesSent );
3140+ bufSizeT & nBytesSent );
3141 inBufClient::fillCondition xRecv ( char * pBuf, bufSizeT nBytesToRecv,
3142- inBufClient::fillParameter parm, bufSizeT & nByesRecv );
3143-
3144- virtual xBlockingStatus blockingState () const = 0;
3145-
3146- virtual outBufClient::flushCondition osdSend ( const char *pBuf, bufSizeT nBytesReq,
3147- bufSizeT & nBytesActual ) = 0;
3148- virtual inBufClient::fillCondition osdRecv ( char *pBuf, bufSizeT nBytesReq,
3149- bufSizeT &nBytesActual ) = 0;
3150+ inBufClient::fillParameter parm, bufSizeT & nByesRecv );
3151+
3152+ virtual xBlockingStatus blockingState () const = 0;
3153+
3154+ virtual outBufClient::flushCondition osdSend ( const char *pBuf, bufSizeT nBytesReq,
3155+ bufSizeT & nBytesActual ) = 0;
3156+ virtual inBufClient::fillCondition osdRecv ( char *pBuf, bufSizeT nBytesReq,
3157+ bufSizeT &nBytesActual ) = 0;
3158 virtual void forceDisconnect () = 0;
3159- caStatus casMonitorCallBack (
3160+ caStatus casMonitorCallBack (
3161 epicsGuard < casClientMutex > &, casMonitor &, const gdd & );
3162 caStatus logBadIdWithFileAndLineno (
3163 epicsGuard < casClientMutex > & guard, const caHdrLargeArray * mp,
3164- const void * dp, const int cacStatus, const char * pFileName,
3165+ const void * dp, const int cacStatus, const char * pFileName,
3166 const unsigned lineno, const unsigned idIn );
3167 void casChannelDestroyFromInterfaceNotify ( casChannelI & chan,
3168 bool immediatedSestroyNeeded );
3169 static void issuePosponeWhenNonePendingWarning ( const char * pReqTypeStr );
3170
3171- casStrmClient ( const casStrmClient & );
3172- casStrmClient & operator = ( const casStrmClient & );
3173+ casStrmClient ( const casStrmClient & );
3174+ casStrmClient & operator = ( const casStrmClient & );
3175 };
3176
3177 #define logBadId(GUARD, MP, DP, CACSTAT, RESID) \
3178@@ -188,4 +195,3 @@
3179 }
3180
3181 #endif // casStrmClienth
3182-
3183
3184=== modified file 'src/cas/io/bsdSocket/casIntfIO.cc'
3185--- src/cas/io/bsdSocket/casIntfIO.cc 2009-07-25 01:04:14 +0000
3186+++ src/cas/io/bsdSocket/casIntfIO.cc 2010-05-14 13:38:34 +0000
3187@@ -1,16 +1,15 @@
3188 /*************************************************************************\
3189-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3190-* National Laboratory.
3191-* Copyright (c) 2002 The Regents of the University of California, as
3192-* Operator of Los Alamos National Laboratory.
3193-* EPICS BASE Versions 3.13.7
3194-* and higher are distributed subject to a Software License Agreement found
3195-* in file LICENSE that is included with this distribution.
3196+ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3197+ * National Laboratory.
3198+ * Copyright (c) 2002 The Regents of the University of California, as
3199+ * Operator of Los Alamos National Laboratory.
3200+ * EPICS BASE Versions 3.13.7
3201+ * and higher are distributed subject to a Software License Agreement found
3202+ * in file LICENSE that is included with this distribution.
3203 \*************************************************************************/
3204-//
3205-// $Id$
3206-//
3207-// Author Jeff Hill
3208+
3209+//
3210+// Author: Jeff Hill
3211 //
3212
3213 #include <stdio.h>
3214@@ -35,11 +34,11 @@
3215 // casIntfIO::casIntfIO()
3216 //
3217 casIntfIO::casIntfIO ( const caNetAddr & addrIn ) :
3218- sock ( INVALID_SOCKET ),
3219+ sock ( INVALID_SOCKET ),
3220 addr ( addrIn.getSockIP() )
3221 {
3222- int status;
3223- osiSocklen_t addrSize;
3224+ int status;
3225+ osiSocklen_t addrSize;
3226 bool portChange;
3227
3228 if ( ! osiSockAttach () ) {
3229@@ -152,9 +151,9 @@
3230 {
3231 static bool oneMsgFlag = false;
3232
3233- struct sockaddr newAddr;
3234- osiSocklen_t length = ( osiSocklen_t ) sizeof ( newAddr );
3235- SOCKET newSock = epicsSocketAccept ( this->sock, & newAddr, & length );
3236+ struct sockaddr newClientAddr;
3237+ osiSocklen_t length = ( osiSocklen_t ) sizeof ( newClientAddr );
3238+ SOCKET newSock = epicsSocketAccept ( this->sock, & newClientAddr, & length );
3239 if ( newSock == INVALID_SOCKET ) {
3240 int errnoCpy = SOCKERRNO;
3241 if ( errnoCpy != SOCK_EWOULDBLOCK && ! oneMsgFlag ) {
3242@@ -166,14 +165,14 @@
3243 }
3244 return NULL;
3245 }
3246- else if ( sizeof ( newAddr ) > (size_t) length ) {
3247+ else if ( sizeof ( newClientAddr ) > (size_t) length ) {
3248 epicsSocketDestroy ( newSock );
3249 errlogPrintf ( "CAS: accept returned bad address len?\n" );
3250 return NULL;
3251 }
3252 oneMsgFlag = false;
3253 ioArgsToNewStreamIO args;
3254- args.addr = newAddr;
3255+ args.clientAddr = newClientAddr;
3256 args.sock = newSock;
3257 casStreamOS * pOS = new casStreamOS ( cas, bufMgr, args );
3258 if ( ! pOS ) {
3259@@ -197,25 +196,25 @@
3260 //
3261 void casIntfIO::setNonBlocking()
3262 {
3263- int status;
3264- osiSockIoctl_t yes = true;
3265+ int status;
3266+ osiSockIoctl_t yes = true;
3267
3268- status = socket_ioctl(this->sock, FIONBIO, &yes); // X aCC 392
3269- if ( status < 0 ) {
3270- char sockErrBuf[64];
3271- epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
3272- errlogPrintf (
3273- "%s:CAS: server non blocking IO set fail because \"%s\"\n",
3274- __FILE__, sockErrBuf );
3275- }
3276+ status = socket_ioctl(this->sock, FIONBIO, &yes); // X aCC 392
3277+ if ( status < 0 ) {
3278+ char sockErrBuf[64];
3279+ epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
3280+ errlogPrintf (
3281+ "%s:CAS: server non blocking IO set fail because \"%s\"\n",
3282+ __FILE__, sockErrBuf );
3283+ }
3284 }
3285-
3286+
3287 //
3288 // casIntfIO::getFD()
3289 //
3290 int casIntfIO::getFD() const
3291 {
3292- return this->sock;
3293+ return this->sock;
3294 }
3295
3296 //
3297@@ -223,9 +222,9 @@
3298 //
3299 void casIntfIO::show(unsigned level) const
3300 {
3301- if (level>2u) {
3302- printf(" casIntfIO::sock = %d\n", this->sock);
3303- }
3304+ if (level>2u) {
3305+ printf(" casIntfIO::sock = %d\n", this->sock);
3306+ }
3307 }
3308
3309 //
3310
3311=== modified file 'src/cas/io/bsdSocket/casStreamIO.cc'
3312--- src/cas/io/bsdSocket/casStreamIO.cc 2009-07-30 23:51:48 +0000
3313+++ src/cas/io/bsdSocket/casStreamIO.cc 2010-05-14 13:38:34 +0000
3314@@ -1,13 +1,14 @@
3315 /*************************************************************************\
3316-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3317-* National Laboratory.
3318-* Copyright (c) 2002 The Regents of the University of California, as
3319-* Operator of Los Alamos National Laboratory.
3320-* EPICS BASE is distributed subject to a Software License Agreement found
3321-* in file LICENSE that is included with this distribution.
3322+ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3323+ * National Laboratory.
3324+ * Copyright (c) 2002 The Regents of the University of California, as
3325+ * Operator of Los Alamos National Laboratory.
3326+ * EPICS BASE is distributed subject to a Software License Agreement found
3327+ * in file LICENSE that is included with this distribution.
3328 \*************************************************************************/
3329+
3330 //
3331-// $Id$
3332+// Author: Jeff Hill
3333 //
3334
3335 #include "errlog.h"
3336@@ -17,11 +18,13 @@
3337
3338 // casStreamIO::casStreamIO()
3339 casStreamIO::casStreamIO ( caServerI & cas, clientBufMemoryManager & bufMgr,
3340- const ioArgsToNewStreamIO & args ) :
3341- casStrmClient ( cas, bufMgr ), sock ( args.sock ), addr ( args.addr),
3342- _osSendBufferSize ( MAX_TCP ), blockingFlag ( xIsBlocking ),
3343- sockHasBeenShutdown ( false )
3344- {
3345+ const ioArgsToNewStreamIO & args ) :
3346+ casStrmClient ( cas, bufMgr, args.clientAddr ),
3347+ sock ( args.sock ),
3348+ _osSendBufferSize ( MAX_TCP ),
3349+ blockingFlag ( xIsBlocking ),
3350+ sockHasBeenShutdown ( false )
3351+{
3352 assert ( sock >= 0 );
3353 int yes = true;
3354 int status;
3355@@ -152,7 +155,7 @@
3356 char sockErrBuf[64];
3357 epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
3358 char buf[64];
3359- ipAddrToA (&this->addr, buf, sizeof(buf));
3360+ this->hostName ( buf, sizeof ( buf ) );
3361 errlogPrintf (
3362 "CAS: TCP socket send to \"%s\" failed because \"%s\"\n",
3363 buf, sockErrBuf );
3364@@ -197,7 +200,7 @@
3365 myerrno != SOCK_ETIMEDOUT ) {
3366 char sockErrBuf[64];
3367 epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
3368- ipAddrToA (&this->addr, buf, sizeof(buf));
3369+ this->hostName ( buf, sizeof ( buf ) );
3370 errlogPrintf(
3371 "CAS: client %s disconnected because \"%s\"\n",
3372 buf, sockErrBuf );
3373@@ -236,10 +239,8 @@
3374 static_cast <const void *> ( this ) );
3375 if (level>1u) {
3376 char buf[64];
3377- ipAddrToA(&this->addr, buf, sizeof(buf));
3378- printf (
3379- "client=%s, port=%x\n",
3380- buf, ntohs(this->addr.sin_port));
3381+ this->hostName ( buf, sizeof ( buf ) );
3382+ printf ( "client = \"%s\"\n", buf );
3383 }
3384 }
3385
3386@@ -286,7 +287,7 @@
3387 char sockErrBuf[64];
3388 epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
3389 char buf[64];
3390- ipAddrToA ( &this->addr, buf, sizeof(buf) );
3391+ this->hostName ( buf, sizeof ( buf ) );
3392 errlogPrintf ("CAS: FIONREAD for %s failed because \"%s\"\n",
3393 buf, sockErrBuf );
3394 }
3395@@ -300,12 +301,6 @@
3396 }
3397 }
3398
3399-// casStreamIO::hostName()
3400-void casStreamIO::hostName ( char * pInBuf, unsigned bufSizeIn ) const
3401-{
3402- ipAddrToA ( & this->addr, pInBuf, bufSizeIn );
3403-}
3404-
3405 // casStreamIO :: osSendBufferSize ()
3406 bufSizeT casStreamIO :: osSendBufferSize () const
3407 {
3408
3409=== modified file 'src/cas/io/bsdSocket/casStreamIO.h'
3410--- src/cas/io/bsdSocket/casStreamIO.h 2009-07-30 23:51:48 +0000
3411+++ src/cas/io/bsdSocket/casStreamIO.h 2010-05-14 13:38:34 +0000
3412@@ -1,13 +1,13 @@
3413-
3414 /*************************************************************************\
3415-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3416-* National Laboratory.
3417-* Copyright (c) 2002 The Regents of the University of California, as
3418-* Operator of Los Alamos National Laboratory.
3419-* EPICS BASE Versions 3.13.7
3420-* and higher are distributed subject to a Software License Agreement found
3421-* in file LICENSE that is included with this distribution.
3422+ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3423+ * National Laboratory.
3424+ * Copyright (c) 2002 The Regents of the University of California, as
3425+ * Operator of Los Alamos National Laboratory.
3426+ * EPICS BASE Versions 3.13.7
3427+ * and higher are distributed subject to a Software License Agreement found
3428+ * in file LICENSE that is included with this distribution.
3429 \*************************************************************************/
3430+
3431 //
3432 // $Id$
3433 //
3434@@ -18,42 +18,34 @@
3435 #include "casStrmClient.h"
3436
3437 struct ioArgsToNewStreamIO {
3438- caNetAddr addr;
3439- SOCKET sock;
3440+ caNetAddr clientAddr;
3441+ SOCKET sock;
3442 };
3443
3444 class casStreamIO : public casStrmClient {
3445 public:
3446- casStreamIO ( caServerI &, clientBufMemoryManager &,
3447+ casStreamIO ( caServerI &, clientBufMemoryManager &,
3448 const ioArgsToNewStreamIO & );
3449- ~casStreamIO ();
3450- int getFD () const;
3451- void xSetNonBlocking ();
3452- const caNetAddr getAddr() const;
3453- void hostName ( char *pBuf, unsigned bufSize ) const;
3454+ ~casStreamIO ();
3455+ int getFD () const;
3456+ void xSetNonBlocking ();
3457 bufSizeT inCircuitBytesPending () const;
3458 bufSizeT osSendBufferSize () const;
3459 private:
3460- SOCKET sock;
3461- struct sockaddr_in addr;
3462+ SOCKET sock;
3463 bufSizeT _osSendBufferSize;
3464- xBlockingStatus blockingFlag;
3465+ xBlockingStatus blockingFlag;
3466
3467 bool sockHasBeenShutdown;
3468- xBlockingStatus blockingState() const;
3469- void osdShow ( unsigned level ) const;
3470- outBufClient::flushCondition osdSend ( const char *pBuf, bufSizeT nBytesReq,
3471- bufSizeT & nBytesActual );
3472- inBufClient::fillCondition osdRecv ( char *pBuf, bufSizeT nBytesReq,
3473- bufSizeT & nBytesActual );
3474+ xBlockingStatus blockingState() const;
3475+ void osdShow ( unsigned level ) const;
3476+ outBufClient::flushCondition osdSend ( const char *pBuf, bufSizeT nBytesReq,
3477+ bufSizeT & nBytesActual );
3478+ inBufClient::fillCondition osdRecv ( char *pBuf, bufSizeT nBytesReq,
3479+ bufSizeT & nBytesActual );
3480 void forceDisconnect ();
3481- casStreamIO ( const casStreamIO & );
3482- casStreamIO & operator = ( const casStreamIO & );
3483+ casStreamIO ( const casStreamIO & );
3484+ casStreamIO & operator = ( const casStreamIO & );
3485 };
3486
3487-inline const caNetAddr casStreamIO::getAddr() const
3488-{
3489- return caNetAddr ( this->addr );
3490-}
3491-
3492 #endif // casStreamIOh
3493
3494=== modified file 'src/libCom/env/envDefs.h'
3495--- src/libCom/env/envDefs.h 2009-06-05 19:56:33 +0000
3496+++ src/libCom/env/envDefs.h 2010-05-14 13:38:34 +0000
3497@@ -49,6 +49,7 @@
3498 epicsShareExtern const ENV_PARAM EPICS_CA_SERVER_PORT;
3499 epicsShareExtern const ENV_PARAM EPICS_CA_MAX_ARRAY_BYTES;
3500 epicsShareExtern const ENV_PARAM EPICS_CA_MAX_SEARCH_PERIOD;
3501+epicsShareExtern const ENV_PARAM EPICS_CA_NAME_SERVERS;
3502 epicsShareExtern const ENV_PARAM EPICS_CAS_INTF_ADDR_LIST;
3503 epicsShareExtern const ENV_PARAM EPICS_CAS_IGNORE_ADDR_LIST;
3504 epicsShareExtern const ENV_PARAM EPICS_CAS_AUTO_BEACON_ADDR_LIST;
3505
3506=== modified file 'src/rsrv/camessage.c'
3507--- src/rsrv/camessage.c 2009-07-09 16:37:24 +0000
3508+++ src/rsrv/camessage.c 2010-05-14 13:38:34 +0000
3509@@ -1,17 +1,16 @@
3510 /*************************************************************************\
3511-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3512-* National Laboratory.
3513-* Copyright (c) 2002 The Regents of the University of California, as
3514-* Operator of Los Alamos National Laboratory.
3515-* EPICS BASE Versions 3.13.7
3516-* and higher are distributed subject to a Software License Agreement found
3517-* in file LICENSE that is included with this distribution.
3518+ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3519+ * National Laboratory.
3520+ * Copyright (c) 2002 The Regents of the University of California, as
3521+ * Operator of Los Alamos National Laboratory.
3522+ * EPICS BASE Versions 3.13.7
3523+ * and higher are distributed subject to a Software License Agreement found
3524+ * in file LICENSE that is included with this distribution.
3525 \*************************************************************************/
3526-/*
3527+
3528+/*
3529 * Author: Jeffrey O. Hill
3530- * hill@luke.lanl.gov
3531- * (505) 665 1831
3532- * Date: 5-88
3533+ *
3534 */
3535
3536 #include <stddef.h>
3537@@ -2190,9 +2189,9 @@
3538 }
3539
3540 /*
3541- * search_reply()
3542+ * search_reply_udp ()
3543 */
3544-static int search_reply ( caHdrLargeArray *mp, void *pPayload, struct client *client )
3545+static int search_reply_udp ( caHdrLargeArray *mp, void *pPayload, struct client *client )
3546 {
3547 struct dbAddr tmp_addr;
3548 ca_uint16_t *pMinorVersion;
3549@@ -2299,6 +2298,66 @@
3550 return RSRV_OK;
3551 }
3552
3553+/*
3554+ * search_reply_tcp ()
3555+ */
3556+static int search_reply_tcp (
3557+ caHdrLargeArray *mp, void *pPayload, struct client *client )
3558+{
3559+ struct dbAddr tmp_addr;
3560+ char *pName = (char *) pPayload;
3561+ int status;
3562+ int spaceAvailOnFreeList;
3563+ size_t spaceNeeded;
3564+ size_t reasonableMonitorSpace = 10;
3565+
3566+ /*
3567+ * check the sanity of the message
3568+ */
3569+ if (mp->m_postsize<=1) {
3570+ log_header ("empty PV name in UDP search request?",
3571+ client, mp, pPayload, 0);
3572+ return RSRV_OK;
3573+ }
3574+ pName[mp->m_postsize-1] = '\0';
3575+
3576+ /* Exit quickly if channel not on this node */
3577+ status = db_name_to_addr (pName, &tmp_addr);
3578+ if (status) {
3579+ DLOG ( 2, ( "CAS: Lookup for channel \"%s\" failed\n", pPayLoad ) );
3580+ if (mp->m_dataType == DOREPLY)
3581+ search_fail_reply ( mp, pPayload, client );
3582+ return RSRV_OK;
3583+ }
3584+
3585+ /*
3586+ * stop further use of server if memory becomes scarse
3587+ */
3588+ spaceAvailOnFreeList = freeListItemsAvail ( rsrvChanFreeList ) > 0
3589+ && freeListItemsAvail ( rsrvEventFreeList ) > reasonableMonitorSpace;
3590+ spaceNeeded = sizeof (struct channel_in_use) +
3591+ reasonableMonitorSpace * sizeof (struct event_ext);
3592+ if ( ! ( osiSufficentSpaceInPool(spaceNeeded) || spaceAvailOnFreeList ) ) {
3593+ SEND_LOCK(client);
3594+ send_err ( mp, ECA_ALLOCMEM, client, "Server memory exhausted" );
3595+ SEND_UNLOCK(client);
3596+ return RSRV_OK;
3597+ }
3598+
3599+ SEND_LOCK ( client );
3600+ status = cas_copy_in_header ( client, CA_PROTO_SEARCH,
3601+ 0, ca_server_port, 0, ~0U, mp->m_available, 0 );
3602+ if ( status != ECA_NORMAL ) {
3603+ SEND_UNLOCK ( client );
3604+ return RSRV_ERROR;
3605+ }
3606+
3607+ cas_commit_msg ( client, 0 );
3608+ SEND_UNLOCK ( client );
3609+
3610+ return RSRV_OK;
3611+}
3612+
3613 typedef int (*pProtoStubTCP) (caHdrLargeArray *mp, void *pPayload, struct client *client);
3614
3615 /*
3616@@ -2312,7 +2371,7 @@
3617 read_action,
3618 write_action,
3619 bad_tcp_cmd_action,
3620- bad_tcp_cmd_action,
3621+ search_reply_tcp,
3622 bad_tcp_cmd_action,
3623 events_off_action,
3624 events_on_action,
3625@@ -2348,7 +2407,7 @@
3626 bad_udp_cmd_action,
3627 bad_udp_cmd_action,
3628 bad_udp_cmd_action,
3629- search_reply,
3630+ search_reply_udp,
3631 bad_udp_cmd_action,
3632 bad_udp_cmd_action,
3633 bad_udp_cmd_action,
3634
3635=== modified file 'src/rsrv/caservertask.c'
3636--- src/rsrv/caservertask.c 2009-07-09 16:37:24 +0000
3637+++ src/rsrv/caservertask.c 2010-05-14 13:38:34 +0000
3638@@ -1,19 +1,18 @@
3639 /*************************************************************************\
3640-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3641-* National Laboratory.
3642-* Copyright (c) 2002 The Regents of the University of California, as
3643-* Operator of Los Alamos National Laboratory.
3644-* EPICS BASE Versions 3.13.7
3645-* and higher are distributed subject to a Software License Agreement found
3646-* in file LICENSE that is included with this distribution.
3647+ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3648+ * National Laboratory.
3649+ * Copyright (c) 2002 The Regents of the University of California, as
3650+ * Operator of Los Alamos National Laboratory.
3651+ * EPICS BASE Versions 3.13.7
3652+ * and higher are distributed subject to a Software License Agreement found
3653+ * in file LICENSE that is included with this distribution.
3654 \*************************************************************************/
3655+
3656 /*
3657 * $Id$
3658 *
3659 * Author: Jeffrey O. Hill
3660- * hill@luke.lanl.gov
3661- * (505) 665 1831
3662- * Date: 5-88
3663+ *
3664 */
3665
3666 #include <stddef.h>
3667@@ -938,6 +937,11 @@
3668 return NULL;
3669 }
3670
3671+ /*
3672+ * add first version message should it be needed
3673+ */
3674+ rsrv_version_reply ( client );
3675+
3676 if ( CASDEBUG > 0 ) {
3677 char buf[64];
3678 ipAddrToDottedIP ( &client->addr, buf, sizeof(buf) );
3679
3680=== modified file 'src/rsrv/server.h'
3681--- src/rsrv/server.h 2009-07-09 16:37:24 +0000
3682+++ src/rsrv/server.h 2010-05-14 13:38:34 +0000
3683@@ -1,17 +1,16 @@
3684 /*************************************************************************\
3685-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3686-* National Laboratory.
3687-* Copyright (c) 2002 The Regents of the University of California, as
3688-* Operator of Los Alamos National Laboratory.
3689-* EPICS BASE Versions 3.13.7
3690-* and higher are distributed subject to a Software License Agreement found
3691-* in file LICENSE that is included with this distribution.
3692+ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3693+ * National Laboratory.
3694+ * Copyright (c) 2002 The Regents of the University of California, as
3695+ * Operator of Los Alamos National Laboratory.
3696+ * EPICS BASE Versions 3.13.7
3697+ * and higher are distributed subject to a Software License Agreement found
3698+ * in file LICENSE that is included with this distribution.
3699 \*************************************************************************/
3700+
3701 /*
3702 * Author: Jeffrey O. Hill
3703- * hill@luke.lanl.gov
3704- * (505) 665 1831
3705- * Date: 5-88
3706+ *
3707 */
3708
3709 #ifndef INCLserverh
3710@@ -29,7 +28,7 @@
3711 #include "asLib.h"
3712 #include "dbAddr.h"
3713 #include "dbNotify.h"
3714-#define CA_MINOR_PROTOCOL_REVISION 11
3715+#define CA_MINOR_PROTOCOL_REVISION 12
3716 #include "caProto.h"
3717 #include "ellLib.h"
3718 #include "epicsTime.h"
3719@@ -47,7 +46,7 @@
3720 ca_uint32_t m_available; /* protocol stub dependent */
3721 ca_uint16_t m_dataType; /* operation data type */
3722 ca_uint16_t m_cmmd; /* operation to be performed */
3723-}caHdrLargeArray;
3724+} caHdrLargeArray;
3725
3726 /*
3727 * !! buf must be the first item in this structure !!

Subscribers

People subscribed via source and target branches