Merged Codeathon 2008 changes (10292..10293 on cvs-trunk branch).
* Fixed conflicts until base compiles * COMPLETELY UNTESTED
This commit is contained in:
+8
-12
@@ -1,16 +1,15 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
* Author: Jeffrey O. Hill
|
||||
* hill@luke.lanl.gov
|
||||
* (505) 665 1831
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
@@ -314,6 +313,3 @@ void CASG::operator delete ( void * )
|
||||
errlogPrintf ( "%s:%d this compiler is confused about placement delete - memory was probably leaked",
|
||||
__FILE__, __LINE__ );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+113
-113
@@ -19,25 +19,25 @@ background-color: #ddf;
|
||||
|
||||
<h1>EPICS R3.14 Channel Access Reference Manual</h1>
|
||||
<address>
|
||||
Jeffrey O. Hill
|
||||
Jeffrey O. Hill
|
||||
</address>
|
||||
|
||||
<p><span style="font-size: x-small; font-weight:lighter;">Los Alamos National
|
||||
Laboratory, SNS Division</span></p>
|
||||
<address>
|
||||
Ralph Lange
|
||||
Ralph Lange
|
||||
</address>
|
||||
|
||||
<p><span style="font-size: x-small; font-weight:lighter;">Helmholtz-Zentrum
|
||||
Berlin (BESSY II)</span></p>
|
||||
|
||||
<p><span style="font-size: xx-small; font-weight:lighter;">Copyright © 2009
|
||||
Helmholtz-Zentrum Berlin für Materialien und Energie GmbH.<br>
|
||||
Copyright © 2002 The University of Chicago, as Operator of Argonne National
|
||||
<p><span style="font-size: xx-small; font-weight:lighter;">Copyright � 2009
|
||||
Helmholtz-Zentrum Berlin f�r Materialien und Energie GmbH.<br>
|
||||
Copyright � 2002 The University of Chicago, as Operator of Argonne National
|
||||
Laboratory.<br>
|
||||
Copyright © 2002 The Regents of the University of California, as Operator of
|
||||
Copyright � 2002 The Regents of the University of California, as Operator of
|
||||
Los Alamos National Laboratory.<br>
|
||||
Copyright © 2002 Berliner Speicherringgesellschaft für Synchrotronstrahlung
|
||||
Copyright � 2002 Berliner Speicherringgesellschaft f�r Synchrotronstrahlung
|
||||
GmbH.</span></p>
|
||||
|
||||
<p><span style="font-size: xx-small; font-weight:lighter;">EPICS BASE Versions
|
||||
@@ -105,7 +105,7 @@ $Date$</span></small></p>
|
||||
|
||||
<h3><a href="#Troublesho">Troubleshooting</a></h3>
|
||||
<ul>
|
||||
<li><a href="#When">When Clients Do Not Connect to Their Server</a>
|
||||
<li><a href="#When">When Clients Do Not Connect to Their Server</a>
|
||||
<ul>
|
||||
<li><a href="#Broadcast">Client and Server Broadcast Addresses Dont
|
||||
Match</a></li>
|
||||
@@ -136,7 +136,7 @@ $Date$</span></small></p>
|
||||
<li><a href="#Connection">Connection Management</a></li>
|
||||
<li><a href="#Thread">Thread Safety and Preemptive Callback to User
|
||||
Code</a></li>
|
||||
<li><a href="#Client2">CA Client Contexts and Application Specific Auxillary
|
||||
<li><a href="#Client2">CA Client Contexts and Application Specific Auxiliary
|
||||
Threads</a></li>
|
||||
<li><a href="#Polling">Polling the CA Client Library From Single Threaded
|
||||
Applications</a></li>
|
||||
@@ -148,7 +148,7 @@ $Date$</span></small></p>
|
||||
handlers</a></li>
|
||||
</ul>
|
||||
|
||||
<h3>Functionality Index </h3>
|
||||
<h3>Functionality Index�</h3>
|
||||
<ul>
|
||||
<li><a href="#ca_context_create">create CA client context</a></li>
|
||||
<li><a href="#ca_context_destroy">terminate CA client context</a></li>
|
||||
@@ -158,7 +158,7 @@ $Date$</span></small></p>
|
||||
<li><a href="#ca_put">write to a channel and wait for initiated activities to
|
||||
complete</a></li>
|
||||
<li><a href="#ca_get">read from a channel</a></li>
|
||||
<li><a href="#ca_add_event">subscribe for state change updates</a></li>
|
||||
<li><a href="#ca_add_event">subscribe�for state change updates</a></li>
|
||||
<li><a href="#ca_clear_event">cancel a subscription</a></li>
|
||||
<li><a href="#ca_pend_io">block for certain requests to complete</a></li>
|
||||
<li><a href="#ca_test_io">test to see if certain requests have
|
||||
@@ -178,13 +178,13 @@ $Date$</span></small></p>
|
||||
<li><a href="#ca_get">ca_array_get_callback</a></li>
|
||||
<li><a href="#ca_put">ca_array_put</a></li>
|
||||
<li><a href="#ca_put">ca_array_put_callback</a></li>
|
||||
<li><a href="#ca_attach_context">ca_attach_context </a></li>
|
||||
<li><a href="#ca_attach_context">ca_attach_context�</a></li>
|
||||
<li><a href="#ca_clear_channel">ca_clear_channel</a></li>
|
||||
<li><a href="#ca_clear_event">ca_clear_subscription</a></li>
|
||||
<li><a href="#ca_client_status">ca_client_status</a></li>
|
||||
<li><a href="#ca_context_create">ca_context_create</a></li>
|
||||
<li><a href="#ca_context_destroy">ca_context_destroy</a></li>
|
||||
<li><a href="CAref.html#ca_client_status">ca_context_status</a></li>
|
||||
<li><a href="#ca_client_status">ca_context_status</a></li>
|
||||
<li><a href="#ca_create_channel">ca_create_channel</a></li>
|
||||
<li><a href="#ca_add_event">ca_create_subscription</a></li>
|
||||
<li><a href="#ca_current_context">ca_current_context</a></li>
|
||||
@@ -299,7 +299,7 @@ is used.</p>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>EPICS_CA_SERVER_PORT</td>
|
||||
<td>i > 5000</td>
|
||||
<td>i�> 5000</td>
|
||||
<td>5064</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -327,7 +327,7 @@ shell that is in use.</p>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>C shell</td>
|
||||
<td>setenv EPICS_CA_ADDR_LIST 1.2.3.4</td>
|
||||
<td>setenv EPICS_CA_ADDR_LIST� 1.2.3.4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>bash</td>
|
||||
@@ -335,7 +335,7 @@ shell that is in use.</p>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>vxWorks shell</td>
|
||||
<td>putenv ( "EPICS_CA_ADDR_LIST =1.2.3.4" )</td>
|
||||
<td>putenv ( "EPICS_CA_ADDR_LIST�=1.2.3.4" )</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DOS command line</td>
|
||||
@@ -362,7 +362,7 @@ to operate over a wide area network (WAN).</p>
|
||||
|
||||
<h3><a name="Network">IP Network Administration Background Information</a></h3>
|
||||
|
||||
<p>Channel Access is implemented using internet protocols (IP). IP addresses
|
||||
<p>Channel Access is implemented�using internet protocols (IP). IP addresses
|
||||
are divided into host and network portions. The boundary between each portion
|
||||
is determined by the IP netmask. Portions of the IP address corresponding to
|
||||
zeros in the netmask specify the hosts address within an IP subnet. Portions of
|
||||
@@ -415,7 +415,7 @@ independent control systems that will share the same network. For instance, a
|
||||
site might set up an operational control system and a test control system on
|
||||
the same network. In this situation it is desirable for the test system and the
|
||||
operational system to use identical PV names without fear of collision. A site
|
||||
might also configure the CA port numbers because some other facility is already
|
||||
might also configure the CA port numbers�because some other facility is already
|
||||
using the default port numbers. The default Channel Access port numbers have
|
||||
been registered with IANA.</p>
|
||||
|
||||
@@ -716,7 +716,7 @@ in the variable EPICS_TS_MIN_WEST.</p>
|
||||
EPICS_CA_MAX_ARRAY_BYTES determines the size of the largest array that may pass
|
||||
through CA. Prior to this version only arrays smaller than 16k bytes could be
|
||||
transfered. The CA libraries maintains a free list of 16384 byte network
|
||||
buffers that are used for ordinary communication. If EPICS_CA_MAX_ARRAY_BYTES
|
||||
buffers that are used for ordinary communication. If EPICS_CA_MAX_ARRAY_BYTES�
|
||||
is larger than 16384 then a second free list of larger data buffers is
|
||||
established and used only after a client send its first large array request.</p>
|
||||
|
||||
@@ -751,7 +751,7 @@ been done to address this issue so far).</em></p>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>EPICS_CAS_SERVER_PORT</td>
|
||||
<td>i > 5000</td>
|
||||
<td>i�> 5000</td>
|
||||
<td>EPICS_CA_SERVER_PORT</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -766,12 +766,12 @@ been done to address this issue so far).</em></p>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>EPICS_CAS_BEACON_PERIOD</td>
|
||||
<td>r > 0.1 seconds</td>
|
||||
<td>r�> 0.1 seconds</td>
|
||||
<td>EPICS_CA_BEACON_PERIOD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>EPICS_CAS_BEACON_PORT</td>
|
||||
<td>i > 5000</td>
|
||||
<td>i�> 5000</td>
|
||||
<td>EPICS_CA_REPEATER_PORT</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -824,8 +824,8 @@ the contents of EPICS_CA_ADDR_LIST is used to augment the list. Otherwise, the
|
||||
list is not augmented.</p>
|
||||
|
||||
<p>The EPICS_CAS_BEACON_PORT parameter specifies the destination port for
|
||||
server beacons. The only exception to this occurs when ports are specified in
|
||||
EPICS_CAS_BEACON_ADDR_LIST or possibly in EPICS_CA_ADDR_LIST. If
|
||||
server beacons. The only exception to this occurs when ports are specified
|
||||
in EPICS_CAS_BEACON_ADDR_LIST or possibly in EPICS_CA_ADDR_LIST. If
|
||||
EPICS_CAS_BEACON_PORT is not specified then beacons are sent to the port
|
||||
specified in EPICS_CA_REPEATER_PORT.</p>
|
||||
|
||||
@@ -846,7 +846,7 @@ not implemet this feature</em>.</p>
|
||||
|
||||
<p>Name resolution requests originating from any of the IP addresses specified
|
||||
in the EPICS_CAS_IGNORE_ADDR_LIST parameter are not replied to.<em>In R3.14 and
|
||||
previous releases the CA server employed by iocCore does not implemet this
|
||||
previous releases the CA server employed by iocCore does not implement this
|
||||
feature.</em></p>
|
||||
|
||||
<h4>Client Configuration that also Applies to Servers</h4>
|
||||
@@ -1082,11 +1082,11 @@ the output.</p>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-w <sec></td>
|
||||
<td>Wait time, specifies CA timeout, default is 1.0 second(s)</td>
|
||||
<td>Wait time, specifies longer CA timeout, default is 1.0 second</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-c</td>
|
||||
<td>Asynchronous get (use ca_get_callback and wait for completion)</td>
|
||||
<td>Asynchronous get (use ca_get_callback instead of ca_get)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-p <prio></td>
|
||||
@@ -1115,7 +1115,7 @@ the output.</p>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-d <type></td>
|
||||
<td>Request specific dbr type; use string (DBR_ prefix may be omitted)
|
||||
<td>Request specific dbr type; use string (DBR_ prefix may be omitted)
|
||||
|
||||
<p>or number of one of the following types:</p>
|
||||
|
||||
@@ -1341,7 +1341,7 @@ the output.</p>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-w <sec></td>
|
||||
<td>Wait time, specifies CA timeout, default is 1.0 second(s)</td>
|
||||
<td>Wait time, specifies longer CA timeout, default is 1.0 second</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-m <mask></td>
|
||||
@@ -1495,7 +1495,7 @@ command line is used.</p>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-w <sec></td>
|
||||
<td>Wait time, specifies CA timeout, default is 1.0 second(s)</td>
|
||||
<td>Wait time, specifies longer CA timeout, default is 1.0 second</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-c</td>
|
||||
@@ -1583,7 +1583,7 @@ etc.</p>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-w <sec></td>
|
||||
<td>Wait time, specifies CA timeout, default is 1.0 second(s)</td>
|
||||
<td>Wait time, specifies longer CA timeout, default is 1.0 second</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-s <level></td>
|
||||
@@ -1973,8 +1973,8 @@ OS and even between different versions of the same OS.</p>
|
||||
<p>If the subscription update producer in the server produces subscription
|
||||
updates faster than the subscription update consumer in the client consumes
|
||||
them, then events have to be discarded if the buffering in the server
|
||||
isn’t allowed to grow to an infinite size. This is a law of nature
|
||||
– based on queuing theory of course.</p>
|
||||
isn't allowed to grow to an infinite size. This is a law of nature
|
||||
- based on queuing theory of course.</p>
|
||||
|
||||
<p>What is done depends on the version of the CA server. All server versions
|
||||
place quotas on the maximum number of subscription updates allowed on the
|
||||
@@ -1996,10 +1996,10 @@ server to resume with subscription updates. This prevents slow clients from
|
||||
getting time warped, but also guarantees that intervening events are discarded
|
||||
until the slow client catches up.</p>
|
||||
|
||||
<p>There is currently no message on the IOC’s console when a particular
|
||||
client is slow on the uptake. A message of this type used to exist many years
|
||||
ago, but it was a source of confusion (and what we will call message noise) so
|
||||
it was removed. </p>
|
||||
<p>There is currently no message on the IOC's console when a
|
||||
particular client is slow on the uptake. A message of this type used to exist
|
||||
many years ago, but it was a source of confusion (and what we will call
|
||||
message noise) so it was removed. </p>
|
||||
|
||||
<p>There is unfortunately no field in the protocol allowing the server to
|
||||
indicate that an intervening subscription update was discarded. We should
|
||||
@@ -2310,7 +2310,7 @@ void myCallback ( struct event_handler_args args )
|
||||
<h3><a name="Channel1">Channel Access Exceptions</a></h3>
|
||||
|
||||
<p>When the server detects a failure, and there is no client call back function
|
||||
attached to the request, then an exception handler is executed in the client.
|
||||
attached to the request, then�an exception handler is executed in the client.
|
||||
The default exception handler prints a message on the console and exits if the
|
||||
exception condition is severe. Certain internal exceptions within the CA client
|
||||
library, and failures detected by the SEVCHK macro may also cause the exception
|
||||
@@ -2332,8 +2332,8 @@ library functions that request them.</p>
|
||||
<h3><a name="Arrays">Arrays</a></h3>
|
||||
|
||||
<p>For routines that require an argument specifying the number of array
|
||||
elements, no more than the process variable's maximum native element count may
|
||||
be requested. The process variable's maximum native element count is available
|
||||
elements, no more than the�process variable's maximum�native element count may
|
||||
be requested. The process variable's�maximum native element count is available
|
||||
from ca_element_count() when the channel is connected. If less elements than
|
||||
the process variable's native element count are requested the requested values
|
||||
will be fetched beginning at element zero. By default CA limits the number of
|
||||
@@ -2383,7 +2383,7 @@ CA's auxiliary threads when the main initiating channel access thread is not
|
||||
inside of a function in the channel access client library. Otherwise, the
|
||||
user's call back functions will be called only when the main initiating channel
|
||||
access thread is executing inside of the CA client library. When the CA client
|
||||
library invokes a user's call back function it will always wait for the current
|
||||
library invokes a user's�call back function it will always wait for the current
|
||||
callback to complete prior to executing another call back function. Programmers
|
||||
enabling preemptive callback should be familiar with using mutex locks to
|
||||
create a reliable multi-threaded program.</p>
|
||||
@@ -2432,6 +2432,7 @@ ca_create_context(ca_disable_preemptive_callback). Once a thread has joined
|
||||
with a CA context it need only make ordinary ca_xxxx() library calls to use the
|
||||
context.</p>
|
||||
|
||||
|
||||
<p>A CA client library context can be shut down and cleaned up, after
|
||||
destroying any channels or application specific threads that are attached to
|
||||
it, by calling <a href="#ca_context_destroy">ca_context_destroy()</a>. The
|
||||
@@ -2484,9 +2485,9 @@ questionable practice for the following reasons.</p>
|
||||
<ul>
|
||||
<li>The vxWorks shell thread runs at the very highest priority in the system
|
||||
and therefore socket calls are made at a priority that is above the
|
||||
priority of tNetTask − a practice that has caused the WRS IP kernel
|
||||
priority of tNetTask - a practice that has caused the WRS IP kernel
|
||||
to get sick in the past. That symptom was observed some time ago, but we
|
||||
don’t know if WRS has fixed the problem.</li>
|
||||
don't know if WRS has fixed the problem.</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>The vxWorks shell thread runs at the very highest priority in the system
|
||||
@@ -2501,7 +2502,7 @@ questionable practice for the following reasons.</p>
|
||||
<ul>
|
||||
<li>In EPICS R3.13 the CA client library installed vxWorks task exit handlers
|
||||
behaved strangely if CA functions were called from the vxWorks shell,
|
||||
ca_task_exit() wasn’t called, and the vxWorks shell restarted. In
|
||||
ca_task_exit() wasn't called, and the vxWorks shell restarted. In
|
||||
EPICS R3.14 vxWorks task exit handlers are not installed and therefore
|
||||
cleanup is solely the responsibility of the user. With EPICS R3.14 the user
|
||||
must call ca_context_destroy or ca_task_exit to clean up on vxWorks. This
|
||||
@@ -2584,7 +2585,7 @@ void ca_context_destroy();</pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
|
||||
<p>Shut down the calling thread's channel access client context and free any
|
||||
<p>Shut down the calling thread's�channel access client context and free any
|
||||
resources allocated. Detach the calling thread from any CA client context.</p>
|
||||
|
||||
<p>Any user-created threads that have attached themselves to the CA context
|
||||
@@ -2637,8 +2638,8 @@ the routine writes a channel identifier into the user's variable of type
|
||||
on a channel.</p>
|
||||
|
||||
<p>The circuit may be initially connected or disconnected depending on the
|
||||
state of the network and the location of the channel. A channel will only enter
|
||||
a connected state after server's address is determined, and only if channel
|
||||
state of the network and the location of the channel. A channel will only�enter
|
||||
a�connected state after server's address is determined, and only if channel
|
||||
access successfully establishes a virtual circuit through the network to the
|
||||
server. Channel access routines that send a request to a server will return
|
||||
ECA_DISCONNCHID if the channel is currently disconnected.</p>
|
||||
@@ -2676,7 +2677,7 @@ time.</p>
|
||||
<dd>A nil terminated process variable name string. EPICS process control
|
||||
function block database variable names are of the form "<record
|
||||
name>.<field name>". If the field name and the period separator
|
||||
are omitted then the "VAL" field is implicit. For example "RFHV01" and
|
||||
are omitted then the "VAL" field is implicit. For example "RFHV01" and
|
||||
"RFHV01.VAL" reference the same EPICS process control function block
|
||||
database variable.</dd>
|
||||
</dl>
|
||||
@@ -2685,7 +2686,7 @@ time.</p>
|
||||
<dd>Optional address of the user's call back function to be run when the
|
||||
connection state changes. Casual users of channel access may decide to
|
||||
set this field to nil or 0 if they do not need to have a call back
|
||||
function run in response to each connection state change event.
|
||||
function run in response to each connection state change event.
|
||||
<p>The following structure is passed <em>by value </em>to the user's
|
||||
connection connection callback function. The <code>op</code> field will
|
||||
be set by the CA client library to <code>CA_OP_CONN_UP</code> when the
|
||||
@@ -2701,8 +2702,8 @@ time.</p>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><code>PUSER</code></dt>
|
||||
<dd>The value of this void pointer argument is retained in
|
||||
storage associated with the specified channel. See the MACROS manual page
|
||||
<dd>The value of this void pointer argument is retained in
|
||||
storage associated with the specified channel. See the MACROS manual page
|
||||
for reading and writing this field. Casual users of channel access may
|
||||
wish to set this field to nil or 0.</dd>
|
||||
</dl>
|
||||
@@ -2743,7 +2744,7 @@ int ca_clear_channel (chid CHID);</code></pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
|
||||
<p>Shutdown and reclaim resources associated with a channel created by
|
||||
<p>Shutdown and reclaim resources�associated with a channel created by
|
||||
ca_create_channel().</p>
|
||||
|
||||
<p>All remote operation requests such as the above are accumulated (buffered)
|
||||
@@ -2753,7 +2754,7 @@ efficiently sent over the network in one message.</p>
|
||||
|
||||
<p>Clearing a channel does not cause its disconnect handler to be called, but
|
||||
clearing a channel does shutdown and reclaim any channel state change event
|
||||
subscriptions (monitors) registered with the channel.</p>
|
||||
subscriptions�(monitors) registered�with the�channel.</p>
|
||||
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
@@ -2787,13 +2788,13 @@ int ca_array_put_callback ( chtype TYPE,
|
||||
|
||||
<p>Write a scalar or array value to a process variable.</p>
|
||||
|
||||
<p>When ca_array_put or ca_put are invoked the client will receive no response
|
||||
<p>When ca_array_put� or ca_put are invoked the client will receive no response
|
||||
unless the request can not be fulfilled in the server. If unsuccessful an
|
||||
exception handler is run on the client side. </p>
|
||||
|
||||
<p>When ca_array_put_callback are invoked the user supplied asynchronous call
|
||||
back is called only after the initiated write operation, and all actions
|
||||
resulting from the initiating write operation, complete.</p>
|
||||
back is called only after the initiated write operation, and all actions
|
||||
resulting from the initiating write operation, complete.</p>
|
||||
|
||||
<p>If unsuccessful the call back function is invoked indicating failure status.
|
||||
</p>
|
||||
@@ -2802,7 +2803,7 @@ resulting from the initiating
|
||||
then the client's call back function is called with failure status, but this
|
||||
does not guarantee that the server did not receive and process the request
|
||||
before the disconnect. If a connection is lost and then resumed outstanding ca
|
||||
put requests are not automatically reissued following reconnect.</p>
|
||||
put requests are not automatically reissued following reconnect.</p>
|
||||
|
||||
<p>All of these functions return ECA_DISCONN if the channel is currently
|
||||
disconnected.</p>
|
||||
@@ -2860,7 +2861,7 @@ do not cause the record to be processed.</p>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><code>PFUNC</code></dt>
|
||||
<dd>address of <a href="#User">user supplied callback function</a> to be
|
||||
<dd>address of <a href="#User">user supplied�callback function</a> to be
|
||||
run when the requested operation completes</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
@@ -2888,7 +2889,7 @@ do not cause the record to be processed.</p>
|
||||
<p>ECA_DISCONN - Channel is disconnected</p>
|
||||
|
||||
<h4>See Also</h4>
|
||||
ca_flush_io()
|
||||
ca_flush_io()
|
||||
|
||||
<p>ca_pend_event()</p>
|
||||
|
||||
@@ -2916,7 +2917,7 @@ assumed to be stable in the application supplied buffer until after ECA_NORMAL
|
||||
is returned from ca_pend_io. If a connection is lost outstanding ca get
|
||||
requests are not automatically reissued following reconnect.</p>
|
||||
When ca_get_callback or ca_array_get_callback are invoked a value is read
|
||||
from the channel and then the user's callback is invoked with a pointer to the
|
||||
from the channel and then the user's callback is invoked with a pointer to the
|
||||
retrieved value. Note that ca_pend_io will not block for the delivery of values
|
||||
requested by ca_get_callback. If the channel disconnects before a ca get
|
||||
callback request can be completed, then the clients call back function is
|
||||
@@ -2992,7 +2993,7 @@ when a CA get request is initiated.</p>
|
||||
<p>ECA_DISCONN - Channel is disconnected</p>
|
||||
|
||||
<h4>See Also</h4>
|
||||
ca_pend_io()
|
||||
ca_pend_io()
|
||||
|
||||
<p>ca_pend_event()</p>
|
||||
|
||||
@@ -3010,7 +3011,7 @@ int ca_create_subscription ( chtype TYPE,
|
||||
<h4>Description</h4>
|
||||
|
||||
<p>Register a state change subscription and specify a call back function to be
|
||||
invoked whenever the process variable undergoes significant state changes. A
|
||||
invoked whenever the process variable undergoes significant state changes. A
|
||||
significant change can be a change in the process variable's value, alarm
|
||||
status, or alarm severity. In the process control function block database the
|
||||
deadband field determines the magnitude of a significant change for for the
|
||||
@@ -3018,7 +3019,7 @@ process variable's value. Each call to this function consumes resources in the
|
||||
client library and potentially a CA server until one of ca_clear_channel or
|
||||
ca_clear_event is called.</p>
|
||||
|
||||
<p>Subscriptions may be installed or canceled against both connected and
|
||||
<p>Subscriptions may be installed or canceled against both connected and
|
||||
disconnected channels. The specified USERFUNC is called once immediately after
|
||||
the subscription is installed with the process variable's current state if the
|
||||
process variable is connected. Otherwise, the specified USERFUNC is called
|
||||
@@ -3027,7 +3028,7 @@ variable. The specified USERFUNC is called immediately with the process
|
||||
variable's current state from within ca_add_event() if the client and the
|
||||
process variable share the same address space.</p>
|
||||
|
||||
<p>If a subscription is installed on a channel in a disconnected state then the
|
||||
<p>If a subscription is installed on a channel in a disconnected state then the
|
||||
requested count will be set to the native maximum element count of the channel
|
||||
if the requested count is larger.</p>
|
||||
|
||||
@@ -3038,8 +3039,8 @@ over the network in one message.</p>
|
||||
|
||||
<p>If at any time after subscribing, read access to the specified process
|
||||
variable is lost, then the call back will be invoked immediately indicating
|
||||
that read access was lost via the status argument. When read access is restored
|
||||
normal event processing will resume starting always with at least one update
|
||||
that read access was lost via the status argument. When read access is restored
|
||||
normal event processing will resume starting always with at least one update
|
||||
indicating the current state of the channel.</p>
|
||||
|
||||
<p>A better name for this function might have been ca_subscribe.</p>
|
||||
@@ -3066,7 +3067,7 @@ indicating the current state of the channel.</p>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><code>USRERFUNC</code></dt>
|
||||
<dd>The address of <a href="#User">user supplied callback function</a> to
|
||||
<dd>The address of <a href="#User">user supplied callback�function</a> to
|
||||
be invoked with each subscription update.</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
@@ -3082,7 +3083,7 @@ indicating the current state of the channel.</p>
|
||||
<dt><code>PEVID</code></dt>
|
||||
<dd>This is a pointer to user supplied event id which is overwritten if
|
||||
successful. This event id can later be used to clear a specific
|
||||
event. This option may may be omitted by passing a nil pointer.</dd>
|
||||
event. This option may may be omitted by passing a nil pointer.</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><code>MASK</code></dt>
|
||||
@@ -3117,7 +3118,7 @@ indicating the current state of the channel.</p>
|
||||
<p>ECA_ADDFAIL - A local database event add failed</p>
|
||||
|
||||
<h4>See Also</h4>
|
||||
ca_pend_event()
|
||||
ca_pend_event()
|
||||
|
||||
<p>ca_flush_io()</p>
|
||||
|
||||
@@ -3130,7 +3131,7 @@ int ca_clear_subscription ( evid EVID );</code></pre>
|
||||
<p>Cancel a subscription.</p>
|
||||
|
||||
<p>All ca_clear_event() requests such as the above are accumulated (buffered)
|
||||
and not forwarded to the server until one of ca_flush_io, ca_pend_io,
|
||||
and not forwarded to the�server until one of ca_flush_io, ca_pend_io,
|
||||
ca_pend_event, or ca_sg_pend are called. This allows several requests to be
|
||||
efficiently sent together in one message.</p>
|
||||
|
||||
@@ -3167,7 +3168,7 @@ time.</p>
|
||||
</ul>
|
||||
|
||||
<p>If ECA_TIMEOUT is returned then get requests may be reissued followed by a
|
||||
subsequent call to ca_pend_io(). Specifically, the function will block only for
|
||||
subsequent call to ca_pend_io(). Specifically, the function will block only for
|
||||
outstanding <a href="#ca_get">ca_get</a> requests issued, and also any channels
|
||||
created specifying a nill connection handler function pointer, after the last
|
||||
call to ca_pend_io() or ca client context creation whichever is later. Note
|
||||
@@ -3177,7 +3178,7 @@ href="#ca_clear_channel">ca_clear_channel</a> is called first.</p>
|
||||
|
||||
<p>If no <a href="#ca_get">ca_get</a> or connection state change events are
|
||||
outstanding then ca_pend_io() will flush the send buffer and return immediately
|
||||
<em>without processing any outstanding channel access background
|
||||
<em>without processing any outstanding channel access background
|
||||
activities</em>.</p>
|
||||
|
||||
<p>The delay specified to ca_pend_io() should take into account worst case
|
||||
@@ -3192,7 +3193,7 @@ pending.</p>
|
||||
<dl>
|
||||
<dt>TIMEOUT</dt>
|
||||
<dd>Specifies the time out interval. A <code>TIMEOUT</code> interval of
|
||||
zero specifies forever.</dd>
|
||||
zero specifies forever.</dd>
|
||||
</dl>
|
||||
|
||||
<h4>Returns</h4>
|
||||
@@ -3205,7 +3206,7 @@ timeout</p>
|
||||
<p>ECA_EVDISALLOW - Function inappropriate for use within an event handler</p>
|
||||
|
||||
<h4>See Also</h4>
|
||||
<a href="#ca_get">ca_get</a>()
|
||||
<a href="#ca_get">ca_get</a>()
|
||||
|
||||
<p><a href="#ca_create_channel">ca_create_channel</a>()</p>
|
||||
|
||||
@@ -3217,12 +3218,12 @@ int ca_test_io();</code></pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
|
||||
<p>This function tests to see if all <a href="#ca_get">ca_get</a> requests are
|
||||
<p>This function tests to see if all <a href="#ca_get">ca_get</a> requests are
|
||||
complete and channels created specifying a nill connection callback function
|
||||
pointer are connected. It will report the status of outstanding <a
|
||||
href="#ca_get">ca_get</a> requests issued, and channels created specifying a
|
||||
nill connection callback function pointer, after the last call to ca_pend_io()
|
||||
or CA context initialization whichever is later.</p>
|
||||
or CA context initialization whichever is later.</p>
|
||||
|
||||
<h4>Returns</h4>
|
||||
|
||||
@@ -3280,8 +3281,8 @@ int ca_flush_io();</pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
|
||||
<p>Flush outstanding IO requests to the server. This routine might be useful
|
||||
to users who need to flush requests prior to performing client side labor in
|
||||
<p>Flush�outstanding IO requests to the server.�This routine might be useful
|
||||
to�users�who need�to flush requests�prior to�performing client side labor in
|
||||
parallel with labor performed in the server.</p>
|
||||
|
||||
<p>Outstanding requests are also sent whenever the buffer which holds them
|
||||
@@ -3324,7 +3325,7 @@ this purpose.</p>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><code>CONTEXT_STRING</code></dt>
|
||||
<dd>A null terminated character string to supply as error context to
|
||||
<dd>A null terminated character string to supply as error context to
|
||||
diagnostics.</dd>
|
||||
</dl>
|
||||
|
||||
@@ -3345,9 +3346,9 @@ back.</p>
|
||||
|
||||
<p>When an error occurs in the server asynchronous to the clients thread then
|
||||
information about this type of error is passed from the server to the client in
|
||||
an exception message. When the client receives this exception message an
|
||||
an exception message. When the client receives this exception message an
|
||||
exception handler callback is called.The default exception handler prints a
|
||||
diagnostic message on the client's standard out and terminates execution if the
|
||||
diagnostic message on the client's standard out and terminates execution if the
|
||||
error condition is severe.</p>
|
||||
|
||||
<p>Note that certain fields in "struct exception_handler_args" are not
|
||||
@@ -3364,7 +3365,7 @@ field should not be used.</p>
|
||||
reinstalled. The following structure is passed by value to the user's
|
||||
callback function. Currently, the <code>op </code>field can be one of
|
||||
<code>CA_OP_GET, CA_OP_PUT, CA_OP_CREATE_CHANNEL, CA_OP_ADD_EVENT,
|
||||
CA_OP_CLEAR_EVENT, or CA_OP_OTHER.</code>
|
||||
CA_OP_CLEAR_EVENT, or CA_OP_OTHER.</code>
|
||||
<pre><code>struct exception_handler_args {
|
||||
void *usr; /* user argument supplied when installed */
|
||||
chanId chid; /* channel id (may be nill) */
|
||||
@@ -3419,7 +3420,7 @@ id="ca_add_fd_">ca_add_fd_registration()</a></code></h3>
|
||||
<h4>Description</h4>
|
||||
|
||||
<p>For use with the services provided by a file descriptor manager (IO
|
||||
multiplexor) such as ""fdmgr.c". A file descriptor manager is often needed when
|
||||
multiplexor) such as "fdmgr.c". A file descriptor manager is often needed when
|
||||
two file descriptor IO intensive libraries such as the EPICS channel access
|
||||
client library and the X window system client library must coexist in the same
|
||||
UNIX process. This function allows an application code to be notified whenever
|
||||
@@ -3535,7 +3536,7 @@ specified channel.</p>
|
||||
<li>whenever the access rights state of a connected channel changes</li>
|
||||
</ul>
|
||||
|
||||
<p>When a channel is created no access rights handler is installed.</p>
|
||||
<p>When a channel is created�no access rights handler is installed.</p>
|
||||
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
@@ -3587,7 +3588,7 @@ chtype ca_field_type ( CHID );</code></pre>
|
||||
<h4>Returns</h4>
|
||||
<dl>
|
||||
<dt><code>TYPE</code></dt>
|
||||
<dd>The data type code will be a member of the set of DBF_XXXX in
|
||||
<dd>The data type code will be�a member of the�set of DBF_XXXX in
|
||||
db_access.h. The constant TYPENOTCONN is returned if the channel is
|
||||
disconnected.<a name="ca_element_count"></a></dd>
|
||||
</dl>
|
||||
@@ -3598,7 +3599,7 @@ unsigned ca_element_count ( CHID );</code></pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
|
||||
<p>Return the maximum array element count in the server for the specified IO
|
||||
<p>Return the maximum array element count in� the server for the specified IO
|
||||
channel.</p>
|
||||
|
||||
<h4>Arguments</h4>
|
||||
@@ -3610,7 +3611,7 @@ channel.</p>
|
||||
<h4>Returns</h4>
|
||||
<dl>
|
||||
<dt><code>COUNT</code></dt>
|
||||
<dd>The maximum array element count in the server. An element count of
|
||||
<dd>The�maximum array element count in� the server. An element count of
|
||||
zero is returned if the channel is disconnected.</dd>
|
||||
</dl>
|
||||
|
||||
@@ -3641,7 +3642,7 @@ void ca_set_puser ( chid CHID, void *PUSER );</code></pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
|
||||
<p>Set a user private void pointer variable retained with each channel for use
|
||||
<p>Set a user private void pointer variable retained with each channel for use
|
||||
at the users discretion.</p>
|
||||
|
||||
<h4>Arguments</h4>
|
||||
@@ -3750,8 +3751,8 @@ int ca_read_access ( CHID );</code></pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
|
||||
<p>Returns boolean true if the client currently has read access to the
|
||||
specified channel and boolean false otherwise.</p>
|
||||
<p>Returns�boolean true�if the client currently has read access to the
|
||||
specified channel and�boolean false�otherwise.</p>
|
||||
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
@@ -3762,8 +3763,8 @@ specified channel and
|
||||
<h4>Returns</h4>
|
||||
<dl>
|
||||
<dt><code>STRING</code></dt>
|
||||
<dd>boolean true if the client currently has read access to the specified
|
||||
channel and boolean false otherwise</dd>
|
||||
<dd>boolean true�if the client currently has read access to the specified
|
||||
channel and�boolean false�otherwise</dd>
|
||||
</dl>
|
||||
|
||||
<h3><code><a name="L6941">ca_write_access()</a></code></h3>
|
||||
@@ -3772,8 +3773,8 @@ int ca_write_access ( CHID );</code></pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
|
||||
<p>Returns boolean true if the client currently has write access to the
|
||||
specified channel and boolean false otherwise.</p>
|
||||
<p>Returns�boolean true�if the client currently has�write access to the
|
||||
specified channel and�boolean false�otherwise.</p>
|
||||
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
@@ -3784,8 +3785,8 @@ specified channel and
|
||||
<h4>Returns</h4>
|
||||
<dl>
|
||||
<dt><code>STRING</code></dt>
|
||||
<dd>boolean true if the client currently has write access to the specified
|
||||
channel and boolean false otherwise</dd>
|
||||
<dd>boolean true if the client currently has write access to the specified
|
||||
channel and boolean false otherwise</dd>
|
||||
</dl>
|
||||
|
||||
<h3><code><a name="dbr_size[]">dbr_size[]</a></code></h3>
|
||||
@@ -3794,12 +3795,12 @@ extern unsigned dbr_size[/*TYPE*/];</code></pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
|
||||
<p>An array that returns the size in bytes for a DBR_XXXX type.</p>
|
||||
<p>An array that returns the size in bytes for a DBR_XXXX type.</p>
|
||||
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
<dt><code>TYPE</code></dt>
|
||||
<dd>The data type code. A member of the set of DBF_XXXX in db_access.h.</dd>
|
||||
<dd>The data type code. A member of the set of DBF_XXXX in db_access.h.</dd>
|
||||
</dl>
|
||||
|
||||
<h4>Returns</h4>
|
||||
@@ -3814,7 +3815,7 @@ unsigned dbr_size_n ( TYPE, COUNT );</code></pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
|
||||
<p>Returns the size in bytes for a DBR_XXXX type with COUNT elements. If the
|
||||
<p>Returns the size in bytes for a DBR_XXXX type with�COUNT elements.�If the
|
||||
DBR type is a structure then the value field is the last field in the
|
||||
structure. If COUNT is greater than one then COUNT-1 elements are appended to
|
||||
the end of the structure so that they can be addressed as an array through a
|
||||
@@ -3850,7 +3851,7 @@ field is returned otherwise the size of the type is returned.</p>
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
<dt><code>TYPE</code></dt>
|
||||
<dd>The data type code. A member of the set of DBF_XXXX in db_access.h.</dd>
|
||||
<dd>The data type code. A member of the set of DBF_XXXX in db_access.h.</dd>
|
||||
</dl>
|
||||
|
||||
<h4>Returns</h4>
|
||||
@@ -3872,7 +3873,7 @@ type.</p>
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
<dt><code>TYPE</code></dt>
|
||||
<dd>The data type code. A member of the set of DBR_XXXX in db_access.h.</dd>
|
||||
<dd>The data type code. A member of the set of DBR_XXXX in db_access.h.</dd>
|
||||
</dl>
|
||||
|
||||
<h4>Returns</h4>
|
||||
@@ -3937,7 +3938,7 @@ SEVCHK ( status, Sync group create failed );</code></pre>
|
||||
<p>ECA_ALLOCMEM - Failed, unable to allocate memory</p>
|
||||
|
||||
<h4>See Also</h4>
|
||||
ca_sg_delete()
|
||||
ca_sg_delete()
|
||||
|
||||
<p>ca_sg_block()</p>
|
||||
|
||||
@@ -3996,7 +3997,7 @@ any pending channel access activities.</p>
|
||||
|
||||
<p>Values written into your program's variables by a channel access synchronous
|
||||
group request should not be referenced by your program until ECA_NORMAL has
|
||||
been received from ca_sg_block(). This routine will process pending channel
|
||||
been received from ca_sg_block(). This routine will process pending channel
|
||||
access background activity while it is waiting.</p>
|
||||
|
||||
<h4>Arguments</h4>
|
||||
@@ -4028,7 +4029,7 @@ SEVCHK(status, Sync group block failed);</code></pre>
|
||||
|
||||
<h3><code><a name="ca_sg_test">ca_sg_test()</a></code></h3>
|
||||
<pre><code>#include <cadef.h>
|
||||
int ca_sg_test ( CA_SYNC_GID GID )</code></pre>
|
||||
int ca_sg_test� ( CA_SYNC_GID GID )</code></pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
|
||||
@@ -4087,7 +4088,7 @@ status = ca_sg_reset(gid);</code></pre>
|
||||
int ca_sg_array_put ( CA_SYNC_GID GID, chtype TYPE,
|
||||
unsigned long COUNT, chid CHID, void *PVALUE );</code></pre>
|
||||
|
||||
<p>Write a value, or array of values, to a channel and increment the
|
||||
<p>Write a value, or array of values, to a channel and increment the
|
||||
outstanding request count of a synchronous group. The ca_sg_array_put
|
||||
functionality is implemented using ca_array_put_callback.</p>
|
||||
|
||||
@@ -4157,8 +4158,8 @@ synchronous group. The ca_sg_array_get functionality is implemented using
|
||||
ca_array_get_callback.</p>
|
||||
|
||||
<p>The values written into your program's variables by ca_sg_get should not be
|
||||
referenced by your program until ECA_NORMAL has been received from ca_sg_block
|
||||
, or until ca_sg_test returns ECA_IODONE.</p>
|
||||
referenced by your program until ECA_NORMAL has been received from ca_sg_block,
|
||||
or until ca_sg_test returns ECA_IODONE.</p>
|
||||
|
||||
<p>All remote operation requests such as the above are accumulated (buffered)
|
||||
and not forwarded to the server until one of ca_flush_io, ca_pend_io,
|
||||
@@ -4186,7 +4187,7 @@ reissued.</p>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><code>CHID</code></dt>
|
||||
<dd>channel identifier</dd>
|
||||
<dd>channel�identifier</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><code>PVALUE</code></dt>
|
||||
@@ -4196,9 +4197,9 @@ reissued.</p>
|
||||
|
||||
<h4>Returns</h4>
|
||||
|
||||
<p>ECA_NORMAL - Normal successful completion </p>
|
||||
<p>ECA_NORMAL - Normal successful completion�</p>
|
||||
|
||||
<p>ECA_BADSYNCGRP - Invalid synchronous group </p>
|
||||
<p>ECA_BADSYNCGRP - Invalid synchronous group�</p>
|
||||
|
||||
<p>ECA_BADCHID - Corrupted CHID</p>
|
||||
|
||||
@@ -4224,7 +4225,7 @@ int ca_context_status ( struct ca_client_context *,
|
||||
<h4>Description</h4>
|
||||
|
||||
<p>Prints information about the client context including, at higher interest
|
||||
levels, status for each channel. Lacking a CA context pointer,
|
||||
levels, status for each channel. Lacking a CA context pointer,
|
||||
ca_client_status() prints information about the calling threads CA context.</p>
|
||||
|
||||
<h4>Arguments</h4>
|
||||
@@ -4404,7 +4405,6 @@ void * PDBR );</code></p>
|
||||
bytes</dd>
|
||||
</dl>
|
||||
|
||||
<p><small>$Id$
|
||||
.</small></p>
|
||||
<p></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Executable
+36
@@ -0,0 +1,36 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#ifndef SearchDest_h
|
||||
#define SearchDest_h
|
||||
|
||||
#include "tsDLList.h"
|
||||
|
||||
class channelNode;
|
||||
class epicsMutex;
|
||||
template < class T > class epicsGuard;
|
||||
|
||||
struct SearchDest :
|
||||
public tsDLNode < SearchDest > {
|
||||
virtual ~SearchDest () {};
|
||||
struct Callback {
|
||||
virtual ~Callback () {};
|
||||
virtual void notify (
|
||||
const caHdr & msg, const void * pPayload,
|
||||
const osiSockAddr & addr, const epicsTime & ) = 0;
|
||||
virtual void show (
|
||||
epicsGuard < epicsMutex > &, unsigned level ) const = 0;
|
||||
};
|
||||
virtual void searchRequest ( epicsGuard < epicsMutex > &,
|
||||
const char * pbuf, size_t len ) = 0;
|
||||
virtual void show ( epicsGuard < epicsMutex > &, unsigned level ) const = 0;
|
||||
};
|
||||
|
||||
#endif // SearchDest_h
|
||||
+4
-1
@@ -40,6 +40,7 @@
|
||||
# define CA_V49(MINOR) ((MINOR)>=9u) /* large arrays, dispatch priorities */
|
||||
# define CA_V410(MINOR) ((MINOR)>=10u) /* beacon counter */
|
||||
# define CA_V411(MINOR) ((MINOR)>=11u) /* sequence numbers in UDP version command */
|
||||
# define CA_V412(MINOR) ((MINOR)>=12u) /* TCP-based search requests */
|
||||
#elif CA_MAJOR_PROTOCOL_REVISION > 4u
|
||||
# define CA_V41(MINOR) ( 1u )
|
||||
# define CA_V42(MINOR) ( 1u )
|
||||
@@ -52,6 +53,7 @@
|
||||
# define CA_V49(MINOR) ( 1u )
|
||||
# define CA_V410(MINOR) ( 1u )
|
||||
# define CA_V411(MINOR) ( 1u )
|
||||
# define CA_V412(MINOR) ( 1u )
|
||||
#else
|
||||
# define CA_V41(MINOR) ( 0u )
|
||||
# define CA_V42(MINOR) ( 0u )
|
||||
@@ -64,7 +66,8 @@
|
||||
# define CA_V49(MINOR) ( 0u )
|
||||
# define CA_V410(MINOR) ( 0u )
|
||||
# define CA_V411(MINOR) ( 0u )
|
||||
#endif
|
||||
# define CA_V412(MINOR) ( 0u )
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These port numbers are only used if the CA repeater and
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
|
||||
+124
-60
@@ -1,14 +1,14 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
*
|
||||
|
||||
/*
|
||||
* L O S A L A M O S
|
||||
* Los Alamos National Laboratory
|
||||
* Los Alamos, New Mexico 87545
|
||||
@@ -16,6 +16,7 @@
|
||||
* Copyright, 1986, The Regents of the University of California.
|
||||
*
|
||||
* Author: Jeff Hill
|
||||
*
|
||||
*/
|
||||
|
||||
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
|
||||
@@ -34,6 +35,7 @@
|
||||
#include "errlog.h"
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "addrList.h"
|
||||
#include "iocinf.h"
|
||||
#include "cac.h"
|
||||
#include "inetAddrID.h"
|
||||
@@ -62,7 +64,7 @@ const cac::pProtoStubTCP cac::tcpJumpTableCAC [] =
|
||||
&cac::readRespAction,
|
||||
&cac::badTCPRespAction,
|
||||
&cac::badTCPRespAction,
|
||||
&cac::badTCPRespAction,
|
||||
&cac::searchRespAction,
|
||||
&cac::badTCPRespAction,
|
||||
&cac::badTCPRespAction,
|
||||
&cac::badTCPRespAction,
|
||||
@@ -177,6 +179,10 @@ cac::cac (
|
||||
strncpy ( this->pUserName, tmp, len );
|
||||
}
|
||||
|
||||
this->_serverPort =
|
||||
envGetInetPortConfigParam ( &EPICS_CA_SERVER_PORT,
|
||||
static_cast <unsigned short> (CA_SERVER_PORT) );
|
||||
|
||||
status = envGetDoubleConfigParam ( &EPICS_CA_CONN_TMO, &this->connTMO );
|
||||
if ( status ) {
|
||||
this->connTMO = CA_CONN_VERIFY_PERIOD;
|
||||
@@ -234,6 +240,32 @@ cac::cac (
|
||||
this->timerQueue.release ();
|
||||
throw;
|
||||
}
|
||||
|
||||
/*
|
||||
* load user configured tcp name server address list,
|
||||
* create virtual circuits, and add them to server table
|
||||
*/
|
||||
ELLLIST dest, tmpList;
|
||||
|
||||
ellInit ( & dest );
|
||||
ellInit ( & tmpList );
|
||||
|
||||
addAddrToChannelAccessAddressList ( &tmpList, &EPICS_CA_NAME_SERVERS, this->_serverPort, false );
|
||||
removeDuplicateAddresses ( &dest, &tmpList, 0 );
|
||||
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
|
||||
while ( osiSockAddrNode *
|
||||
pNode = reinterpret_cast < osiSockAddrNode * > ( ellGet ( & dest ) ) ) {
|
||||
tcpiiu * piiu = NULL;
|
||||
bool newIIU = findOrCreateVirtCircuit (
|
||||
guard, pNode->addr, cacChannel::priorityDefault,
|
||||
piiu, CA_UKN_MINOR_VERSION, true );
|
||||
free ( pNode );
|
||||
if ( newIIU ) {
|
||||
piiu->start ( guard );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cac::~cac ()
|
||||
@@ -468,7 +500,8 @@ cacChannel & cac::createChannel (
|
||||
if ( ! this->pudpiiu ) {
|
||||
this->pudpiiu = new udpiiu (
|
||||
guard, this->timerQueue, this->cbMutex,
|
||||
this->mutex, this->notify, *this );
|
||||
this->mutex, this->notify, *this, this->_serverPort,
|
||||
this->searchDestList );
|
||||
}
|
||||
|
||||
nciu * pNetChan = new ( this->channelFreeList )
|
||||
@@ -477,6 +510,57 @@ cacChannel & cac::createChannel (
|
||||
return *pNetChan;
|
||||
}
|
||||
|
||||
bool cac::findOrCreateVirtCircuit (
|
||||
epicsGuard < epicsMutex > & guard, const osiSockAddr & addr,
|
||||
unsigned priority, tcpiiu *& piiu, unsigned minorVersionNumber,
|
||||
const bool nameService )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
bool newIIU = false;
|
||||
|
||||
if ( piiu ) {
|
||||
if ( ! piiu->alive ( guard ) ) {
|
||||
return newIIU;
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
autoPtrFreeList < tcpiiu, 32, epicsMutexNOOP > pnewiiu (
|
||||
this->freeListVirtualCircuit,
|
||||
new ( this->freeListVirtualCircuit ) tcpiiu (
|
||||
*this, this->mutex, this->cbMutex, this->notify, this->connTMO,
|
||||
this->timerQueue, addr, this->comBufMemMgr, minorVersionNumber,
|
||||
this->ipToAEngine, priority, nameService ) );
|
||||
|
||||
bhe * pBHE = this->beaconTable.lookup ( addr.ia );
|
||||
if ( ! pBHE ) {
|
||||
pBHE = new ( this->bheFreeList )
|
||||
bhe ( this->mutex, epicsTime (), 0u, addr.ia );
|
||||
if ( this->beaconTable.add ( *pBHE ) < 0 ) {
|
||||
return newIIU;
|
||||
}
|
||||
}
|
||||
this->serverTable.add ( *pnewiiu );
|
||||
this->circuitList.add ( *pnewiiu );
|
||||
pBHE->registerIIU ( guard, *pnewiiu );
|
||||
piiu = pnewiiu.release ();
|
||||
newIIU = true;
|
||||
}
|
||||
catch ( std :: exception & except ) {
|
||||
errlogPrintf (
|
||||
"CAC: exception during virtual circuit creation \"%s\"\n",
|
||||
except.what () );
|
||||
return newIIU;
|
||||
}
|
||||
catch ( ... ) {
|
||||
errlogPrintf (
|
||||
"CAC: Nonstandard exception during virtual circuit creation\n" );
|
||||
return newIIU;
|
||||
}
|
||||
}
|
||||
return newIIU;
|
||||
}
|
||||
|
||||
void cac::transferChanToVirtCircuit (
|
||||
unsigned cid, unsigned sid, // X aCC 431
|
||||
ca_uint16_t typeCode, arrayElementCount count,
|
||||
@@ -484,7 +568,7 @@ void cac::transferChanToVirtCircuit (
|
||||
const epicsTime & currentTime )
|
||||
{
|
||||
if ( addr.sa.sa_family != AF_INET ) {
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
@@ -501,6 +585,7 @@ void cac::transferChanToVirtCircuit (
|
||||
* Ignore duplicate search replies
|
||||
*/
|
||||
osiSockAddr chanAddr = pChan->getPIIU(guard)->getNetworkAddress (guard);
|
||||
|
||||
if ( chanAddr.sa.sa_family != AF_UNSPEC ) {
|
||||
if ( ! sockAddrAreIdentical ( &addr, &chanAddr ) ) {
|
||||
char acc[64];
|
||||
@@ -519,52 +604,12 @@ void cac::transferChanToVirtCircuit (
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* look for an existing virtual circuit
|
||||
*/
|
||||
bool newIIU = false;
|
||||
caServerID servID ( addr.ia, pChan->getPriority(guard) );
|
||||
tcpiiu * piiu = this->serverTable.lookup ( servID );
|
||||
if ( piiu ) {
|
||||
if ( ! piiu->alive ( guard ) ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
autoPtrFreeList < tcpiiu, 32, epicsMutexNOOP > pnewiiu (
|
||||
this->freeListVirtualCircuit,
|
||||
new ( this->freeListVirtualCircuit ) tcpiiu (
|
||||
*this, this->mutex, this->cbMutex, this->notify, this->connTMO,
|
||||
this->timerQueue, addr, this->comBufMemMgr, minorVersionNumber,
|
||||
this->ipToAEngine, pChan->getPriority(guard) ) );
|
||||
bhe * pBHE = this->beaconTable.lookup ( addr.ia );
|
||||
if ( ! pBHE ) {
|
||||
pBHE = new ( this->bheFreeList )
|
||||
bhe ( this->mutex, epicsTime (), 0u, addr.ia );
|
||||
if ( this->beaconTable.add ( *pBHE ) < 0 ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
this->serverTable.add ( *pnewiiu );
|
||||
this->circuitList.add ( *pnewiiu );
|
||||
this->iiuExistenceCount++;
|
||||
pBHE->registerIIU ( guard, *pnewiiu );
|
||||
piiu = pnewiiu.release ();
|
||||
newIIU = true;
|
||||
}
|
||||
catch ( std :: exception & except ) {
|
||||
errlogPrintf (
|
||||
"CAC: exception during virtual circuit creation \"%s\"\n",
|
||||
except.what () );
|
||||
return;
|
||||
}
|
||||
catch ( ... ) {
|
||||
errlogPrintf (
|
||||
"CAC: nonstandard exception during virtual circuit creation\n" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool newIIU = findOrCreateVirtCircuit (
|
||||
guard, addr,
|
||||
pChan->getPriority(guard), piiu, minorVersionNumber, false );
|
||||
|
||||
// must occur before moving to new iiu
|
||||
pChan->getPIIU(guard)->uninstallChanDueToSuccessfulSearchResponse (
|
||||
@@ -746,9 +791,10 @@ netSubscription & cac::subscriptionRequest (
|
||||
return *pIO.release ();
|
||||
}
|
||||
|
||||
bool cac::versionAction ( callbackManager &, tcpiiu &,
|
||||
const epicsTime &, const caHdrLargeArray &, void * )
|
||||
bool cac::versionAction ( callbackManager &, tcpiiu & iiu,
|
||||
const epicsTime &, const caHdrLargeArray & msg, void * )
|
||||
{
|
||||
iiu.versionRespNotify ( msg );
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -831,6 +877,15 @@ bool cac::readNotifyRespAction ( callbackManager &, tcpiiu & iiu,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cac::searchRespAction ( callbackManager &, tcpiiu & iiu,
|
||||
const epicsTime & currentTime, const caHdrLargeArray & msg,
|
||||
void * /* pMsgBdy */ )
|
||||
{
|
||||
assert ( this->pudpiiu );
|
||||
iiu.searchRespNotify ( currentTime, msg );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cac::eventRespAction ( callbackManager &, tcpiiu &iiu,
|
||||
const epicsTime &, const caHdrLargeArray & hdr, void * pMsgBdy )
|
||||
{
|
||||
@@ -1076,7 +1131,7 @@ bool cac::createChannelRespAction (
|
||||
}
|
||||
|
||||
bool cac::verifyAndDisconnectChan (
|
||||
callbackManager & mgr, tcpiiu &,
|
||||
callbackManager & mgr, tcpiiu &,
|
||||
const epicsTime &, const caHdrLargeArray & hdr, void * /* pMsgBody */ )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
@@ -1139,6 +1194,7 @@ void cac::destroyIIU ( tcpiiu & iiu )
|
||||
{
|
||||
callbackManager mgr ( this->notify, this->cbMutex );
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
|
||||
if ( iiu.channelCount ( guard ) ) {
|
||||
char hostNameTmp[64];
|
||||
iiu.getHostName ( guard, hostNameTmp, sizeof ( hostNameTmp ) );
|
||||
@@ -1166,13 +1222,14 @@ void cac::destroyIIU ( tcpiiu & iiu )
|
||||
// this waits for send/recv threads to exit
|
||||
// this also uses the cac free lists so cac must wait
|
||||
// for this to finish before it shuts down
|
||||
|
||||
iiu.~tcpiiu ();
|
||||
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
this->freeListVirtualCircuit.release ( & iiu );
|
||||
this->iiuExistenceCount--;
|
||||
// signal iiu uninstal event so that cac can properly shut down
|
||||
// signal iiu uninstall event so that cac can properly shut down
|
||||
this->iiuUninstall.signal();
|
||||
}
|
||||
// do not touch "this" after lock is released above
|
||||
@@ -1230,3 +1287,10 @@ void cac::pvMultiplyDefinedNotify ( msgForMultiplyDefinedPV & mfmdpv,
|
||||
this->mdpvFreeList.release ( & mfmdpv );
|
||||
}
|
||||
|
||||
void cac::registerSearchDest (
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
SearchDest & req )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
this->searchDestList.add ( req );
|
||||
}
|
||||
|
||||
+34
-18
@@ -1,25 +1,23 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
*
|
||||
*
|
||||
|
||||
/*
|
||||
* L O S A L A M O S
|
||||
* Los Alamos National Laboratory
|
||||
* Los Alamos, New Mexico 87545
|
||||
*
|
||||
*
|
||||
* Copyright, 1986, The Regents of the University of California.
|
||||
*
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*
|
||||
*
|
||||
* Author: Jeff Hill
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef cach
|
||||
@@ -182,6 +180,13 @@ public:
|
||||
int status, const char * pContext,
|
||||
const char * pFileName, unsigned lineNo );
|
||||
|
||||
// search destination management
|
||||
void registerSearchDest (
|
||||
epicsGuard < epicsMutex > &, SearchDest & req );
|
||||
bool findOrCreateVirtCircuit (
|
||||
epicsGuard < epicsMutex > &, const osiSockAddr &,
|
||||
unsigned, tcpiiu *&, unsigned, const bool );
|
||||
|
||||
// diagnostics
|
||||
unsigned circuitCount ( epicsGuard < epicsMutex > & ) const;
|
||||
void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
|
||||
@@ -191,6 +196,7 @@ public:
|
||||
int varArgsPrintFormated (
|
||||
epicsGuard < epicsMutex > & callbackControl,
|
||||
const char *pformat, va_list args ) const;
|
||||
double connectionTimeout ( epicsGuard < epicsMutex > & );
|
||||
|
||||
// buffer management
|
||||
char * allocateSmallBufferTCP ();
|
||||
@@ -235,6 +241,7 @@ private:
|
||||
resTable < bhe, inetAddrID > beaconTable;
|
||||
resTable < tcpiiu, caServerID > serverTable;
|
||||
tsDLList < tcpiiu > circuitList;
|
||||
tsDLList < SearchDest > searchDestList;
|
||||
tsFreeList
|
||||
< class tcpiiu, 32, epicsMutexNOOP >
|
||||
freeListVirtualCircuit;
|
||||
@@ -275,6 +282,7 @@ private:
|
||||
unsigned maxRecvBytesTCP;
|
||||
unsigned maxContigFrames;
|
||||
unsigned beaconAnomalyCount;
|
||||
unsigned short _serverPort;
|
||||
unsigned iiuExistenceCount;
|
||||
|
||||
void recycleReadNotifyIO (
|
||||
@@ -303,6 +311,8 @@ private:
|
||||
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
|
||||
bool writeNotifyRespAction ( callbackManager &, tcpiiu &,
|
||||
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
|
||||
bool searchRespAction ( callbackManager &, tcpiiu &,
|
||||
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
|
||||
bool readNotifyRespAction ( callbackManager &, tcpiiu &,
|
||||
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
|
||||
bool eventRespAction ( callbackManager &, tcpiiu &,
|
||||
@@ -444,11 +454,17 @@ inline const char * cac :: pLocalHostName ()
|
||||
return _refLocalHostName->pointer ();
|
||||
}
|
||||
|
||||
inline unsigned cac ::
|
||||
inline unsigned cac ::
|
||||
maxContiguousFrames ( epicsGuard < epicsMutex > & ) const
|
||||
{
|
||||
return maxContigFrames;
|
||||
}
|
||||
|
||||
inline double cac ::
|
||||
connectionTimeout ( epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
return this->connTMO;
|
||||
}
|
||||
|
||||
#endif // ifdef cach
|
||||
|
||||
|
||||
+8
-7
@@ -1,12 +1,13 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
*
|
||||
* L O S A L A M O S
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@
|
||||
# include "shareLib.h"
|
||||
#endif
|
||||
|
||||
#define CA_MINOR_PROTOCOL_REVISION 11
|
||||
#define CA_MINOR_PROTOCOL_REVISION 12
|
||||
#include "caProto.h"
|
||||
|
||||
#include "cacIO.h"
|
||||
|
||||
+116
-36
@@ -1,16 +1,14 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* L O S A L A M O S
|
||||
* Los Alamos National Laboratory
|
||||
* Los Alamos, New Mexico 87545
|
||||
@@ -18,6 +16,7 @@
|
||||
* Copyright, 1986, The Regents of the University of California.
|
||||
*
|
||||
* Author: Jeff Hill
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@@ -228,7 +227,6 @@ void tcpSendThread::run ()
|
||||
epicsThreadSleep ( 0.1 );
|
||||
}
|
||||
}
|
||||
|
||||
this->iiu.cacRef.destroyIIU ( this->iiu );
|
||||
}
|
||||
|
||||
@@ -236,7 +234,6 @@ unsigned tcpiiu::sendBytes ( const void *pBuf,
|
||||
unsigned nBytesInBuf, const epicsTime & currentTime )
|
||||
{
|
||||
unsigned nBytes = 0u;
|
||||
|
||||
assert ( nBytesInBuf <= INT_MAX );
|
||||
|
||||
this->sendDog.start ( currentTime );
|
||||
@@ -477,7 +474,7 @@ void tcpRecvThread::run ()
|
||||
pComBuf->fillFromWire ( this->iiu, stat );
|
||||
|
||||
epicsTime currentTime = epicsTime::getCurrent ();
|
||||
|
||||
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->iiu.mutex );
|
||||
|
||||
@@ -634,17 +631,23 @@ void tcpRecvThread::connect (
|
||||
continue;
|
||||
}
|
||||
else if ( errnoCpy == SOCK_SHUTDOWN ) {
|
||||
break;
|
||||
if ( ! this->iiu._nameService ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
else {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
errlogPrintf ( "CAC: Unable to connect because \"%s\"\n",
|
||||
sockErrBuf );
|
||||
this->iiu.disconnectNotify ( guard );
|
||||
break;
|
||||
if ( ! this->iiu._nameService ) {
|
||||
this->iiu.disconnectNotify ( guard );
|
||||
break;
|
||||
}
|
||||
}
|
||||
epicsThreadSleep ( this->iiu.cacRef.connectionTimeout ( guard ) );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -659,7 +662,8 @@ tcpiiu::tcpiiu (
|
||||
epicsTimerQueue & timerQueue, const osiSockAddr & addrIn,
|
||||
comBufMemoryManager & comBufMemMgrIn,
|
||||
unsigned minorVersion, ipAddrToAsciiEngine & engineIn,
|
||||
const cacChannel::priLev & priorityIn ) :
|
||||
const cacChannel::priLev & priorityIn,
|
||||
const bool nameService ) :
|
||||
caServerID ( addrIn.ia, priorityIn ),
|
||||
hostNameCacheInstance ( addrIn, engineIn ),
|
||||
recvThread ( *this, cbMutexIn, ctxNotifyIn, "CAC-TCP-recv",
|
||||
@@ -680,6 +684,7 @@ tcpiiu::tcpiiu (
|
||||
comBufMemMgr ( comBufMemMgrIn ),
|
||||
cacRef ( cac ),
|
||||
pCurData ( cac.allocateSmallBufferTCP () ),
|
||||
pSearchDest ( NULL ),
|
||||
mutex ( mutexIn ),
|
||||
cbMutex ( cbMutexIn ),
|
||||
minorProtocolVersion ( minorVersion ),
|
||||
@@ -691,6 +696,7 @@ tcpiiu::tcpiiu (
|
||||
unacknowledgedSendBytes ( 0u ),
|
||||
channelCountTot ( 0u ),
|
||||
_receiveThreadIsBusy ( false ),
|
||||
_nameService ( nameService ),
|
||||
busyStateDetected ( false ),
|
||||
flowControlActive ( false ),
|
||||
echoRequestPending ( false ),
|
||||
@@ -815,6 +821,14 @@ tcpiiu::tcpiiu (
|
||||
}
|
||||
# endif
|
||||
|
||||
if ( _nameService ) {
|
||||
#pragma message ( "exception thrown here might not cleanup socket" )
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
SearchDestTCP * pSearchDestTCP = new SearchDestTCP ( this, cacRef, addrIn );
|
||||
cacRef.registerSearchDest ( guard, *pSearchDestTCP );
|
||||
this->pSearchDest = pSearchDestTCP;
|
||||
}
|
||||
|
||||
memset ( (void *) &this->curMsg, '\0', sizeof ( this->curMsg ) );
|
||||
}
|
||||
|
||||
@@ -831,6 +845,7 @@ void tcpiiu::initiateCleanShutdown (
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
|
||||
if ( this->state == iiucs_connected ) {
|
||||
if ( this->unresponsiveCircuit ) {
|
||||
this->initiateAbortShutdown ( guard );
|
||||
@@ -1014,8 +1029,12 @@ void tcpiiu::initiateAbortShutdown (
|
||||
//
|
||||
// tcpiiu::~tcpiiu ()
|
||||
//
|
||||
tcpiiu::~tcpiiu ()
|
||||
tcpiiu :: ~tcpiiu ()
|
||||
{
|
||||
if ( this->pSearchDest ) {
|
||||
this->pSearchDest->disable ();
|
||||
}
|
||||
|
||||
this->sendThread.exitWait ();
|
||||
this->recvThread.exitWait ();
|
||||
this->sendDog.cancel ();
|
||||
@@ -1830,7 +1849,9 @@ void tcpiiu::disconnectAllChannels (
|
||||
|
||||
this->channelCountTot = 0u;
|
||||
|
||||
this->initiateCleanShutdown ( guard );
|
||||
if ( ! _nameService ) {
|
||||
this->initiateCleanShutdown ( guard );
|
||||
}
|
||||
}
|
||||
|
||||
void tcpiiu::unlinkAllChannels (
|
||||
@@ -1839,7 +1860,7 @@ void tcpiiu::unlinkAllChannels (
|
||||
{
|
||||
cbGuard.assertIdenticalMutex ( this->cbMutex );
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
|
||||
|
||||
while ( nciu * pChan = this->createReqPend.get () ) {
|
||||
pChan->serviceShutdownNotify ( cbGuard, guard );
|
||||
}
|
||||
@@ -1890,7 +1911,9 @@ void tcpiiu::unlinkAllChannels (
|
||||
|
||||
this->channelCountTot = 0u;
|
||||
|
||||
this->initiateCleanShutdown ( guard );
|
||||
if ( ! _nameService ) {
|
||||
this->initiateCleanShutdown ( guard );
|
||||
}
|
||||
}
|
||||
|
||||
void tcpiiu::installChannel (
|
||||
@@ -1909,20 +1932,6 @@ void tcpiiu::installChannel (
|
||||
this->sendThreadFlushEvent.signal ();
|
||||
}
|
||||
|
||||
void tcpiiu::nameResolutionMsgEndNotify ()
|
||||
{
|
||||
bool wakeupNeeded = false;
|
||||
{
|
||||
epicsGuard < epicsMutex > autoMutex ( this->mutex );
|
||||
if ( this->createReqPend.count () ) {
|
||||
wakeupNeeded = true;
|
||||
}
|
||||
}
|
||||
if ( wakeupNeeded ) {
|
||||
this->sendThreadFlushEvent.signal ();
|
||||
}
|
||||
}
|
||||
|
||||
bool tcpiiu :: connectNotify (
|
||||
epicsGuard < epicsMutex > & guard, nciu & chan )
|
||||
{
|
||||
@@ -1980,7 +1989,7 @@ void tcpiiu::uninstallChan (
|
||||
}
|
||||
chan.channelNode::listMember = channelNode::cs_none;
|
||||
this->channelCountTot--;
|
||||
if ( this->channelCountTot == 0 ) {
|
||||
if ( this->channelCountTot == 0 && ! _nameService ) {
|
||||
this->initiateCleanShutdown ( guard );
|
||||
}
|
||||
}
|
||||
@@ -2100,5 +2109,76 @@ bool tcpiiu::searchMsg (
|
||||
guard, id, pName, nameLength );
|
||||
}
|
||||
|
||||
tcpiiu :: SearchDestTCP :: SearchDestTCP (
|
||||
tcpiiu * tcpiiuIn, cac & cacIn, const osiSockAddr & addrIn ) :
|
||||
_ptcpiiu ( tcpiiuIn ),
|
||||
_cac ( cacIn ),
|
||||
_addr ( addrIn ),
|
||||
_active ( true )
|
||||
{
|
||||
}
|
||||
|
||||
void tcpiiu :: SearchDestTCP :: disable ()
|
||||
{
|
||||
_active = false;
|
||||
}
|
||||
|
||||
void tcpiiu :: SearchDestTCP :: searchRequest (
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
const char * pBuf, size_t len )
|
||||
{
|
||||
// restart circuit if it was shut down
|
||||
if ( ! _active ) {
|
||||
tcpiiu * piiu = NULL;
|
||||
bool newIIU = _cac.findOrCreateVirtCircuit (
|
||||
guard, _addr, cacChannel::priorityDefault,
|
||||
piiu, CA_UKN_MINOR_VERSION, true );
|
||||
if ( newIIU ) {
|
||||
piiu->start ( guard );
|
||||
}
|
||||
_ptcpiiu = piiu;
|
||||
_active = true;
|
||||
}
|
||||
|
||||
// does this server support TCP-based name resolution
|
||||
if ( CA_V412 ( _ptcpiiu->minorProtocolVersion ) ) {
|
||||
guard.assertIdenticalMutex ( _ptcpiiu->mutex );
|
||||
assert ( CA_MESSAGE_ALIGN ( len ) == len );
|
||||
comQueSendMsgMinder minder ( _ptcpiiu->sendQue, guard );
|
||||
_ptcpiiu->sendQue.pushString ( pBuf, len );
|
||||
minder.commit ();
|
||||
_ptcpiiu->flushRequest ( guard );
|
||||
}
|
||||
}
|
||||
|
||||
void tcpiiu :: SearchDestTCP :: show (
|
||||
epicsGuard < epicsMutex > & guard, unsigned level ) const
|
||||
{
|
||||
:: printf ( "tcpiiu :: SearchDestTCP\n" );
|
||||
}
|
||||
|
||||
void tcpiiu :: versionRespNotify ( const caHdrLargeArray & msg )
|
||||
{
|
||||
this->minorProtocolVersion = msg.m_count;
|
||||
}
|
||||
|
||||
void tcpiiu :: searchRespNotify (
|
||||
const epicsTime & currentTime, const caHdrLargeArray & msg )
|
||||
{
|
||||
/*
|
||||
* the type field is abused to carry the port number
|
||||
* so that we can have multiple servers on one host
|
||||
*/
|
||||
osiSockAddr serverAddr;
|
||||
if ( msg.m_cid != INADDR_BROADCAST ) {
|
||||
serverAddr.ia.sin_family = AF_INET;
|
||||
serverAddr.ia.sin_addr.s_addr = htonl ( msg.m_cid );
|
||||
serverAddr.ia.sin_port = htons ( msg.m_dataType );
|
||||
}
|
||||
else {
|
||||
serverAddr = this->address ();
|
||||
}
|
||||
cacRef.transferChanToVirtCircuit
|
||||
( msg.m_available, msg.m_cid, 0xffff,
|
||||
0, minorProtocolVersion, serverAddr, currentTime );
|
||||
}
|
||||
|
||||
+213
-82
@@ -1,12 +1,13 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
*
|
||||
* L O S A L A M O S
|
||||
@@ -73,7 +74,9 @@ udpiiu::udpiiu (
|
||||
epicsMutex & cbMutexIn,
|
||||
epicsMutex & cacMutexIn,
|
||||
cacContextNotify & ctxNotifyIn,
|
||||
cac & cac ) :
|
||||
cac & cac,
|
||||
unsigned port,
|
||||
tsDLList < SearchDest > & searchDestListIn ) :
|
||||
recvThread ( *this, ctxNotifyIn, cbMutexIn, "CAC-UDP",
|
||||
epicsThreadGetStackSize ( epicsThreadStackMedium ),
|
||||
cac::lowestPriorityLevelAbove (
|
||||
@@ -95,7 +98,7 @@ udpiiu::udpiiu (
|
||||
lastReceivedSeqNo ( 0 ),
|
||||
sock ( 0 ),
|
||||
repeaterPort ( 0 ),
|
||||
serverPort ( 0 ),
|
||||
serverPort ( port ),
|
||||
localPort ( 0 ),
|
||||
shutdownCmd ( false ),
|
||||
lastReceivedSeqNoIsValid ( false )
|
||||
@@ -150,10 +153,6 @@ udpiiu::udpiiu (
|
||||
envGetInetPortConfigParam ( &EPICS_CA_REPEATER_PORT,
|
||||
static_cast <unsigned short> (CA_REPEATER_PORT) );
|
||||
|
||||
this->serverPort =
|
||||
envGetInetPortConfigParam ( &EPICS_CA_SERVER_PORT,
|
||||
static_cast <unsigned short> (CA_SERVER_PORT) );
|
||||
|
||||
this->sock = epicsSocketCreate ( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
|
||||
if ( this->sock == INVALID_SOCKET ) {
|
||||
char sockErrBuf[64];
|
||||
@@ -238,8 +237,19 @@ udpiiu::udpiiu (
|
||||
* load user and auto configured
|
||||
* broadcast address list
|
||||
*/
|
||||
ellInit ( & this->dest ); // X aCC 392
|
||||
configureChannelAccessAddressList ( & this->dest, this->sock, this->serverPort );
|
||||
ELLLIST dest;
|
||||
ellInit ( & dest );
|
||||
configureChannelAccessAddressList ( & dest, this->sock, this->serverPort );
|
||||
while ( osiSockAddrNode *
|
||||
pNode = reinterpret_cast < osiSockAddrNode * > ( ellGet ( & dest ) ) ) {
|
||||
SearchDestUDP & searchDest = *
|
||||
new SearchDestUDP ( pNode->addr, *this );
|
||||
_searchDestList.add ( searchDest );
|
||||
free ( pNode );
|
||||
}
|
||||
|
||||
/* add list of tcp name service addresses */
|
||||
_searchDestList.add ( searchDestListIn );
|
||||
|
||||
caStartRepeaterIfNotInstalled ( this->repeaterPort );
|
||||
|
||||
@@ -267,12 +277,13 @@ udpiiu::~udpiiu ()
|
||||
|
||||
// avoid use of ellFree because problems on windows occur if the
|
||||
// free is in a different DLL than the malloc
|
||||
ELLNODE * nnode = this->dest.node.next;
|
||||
while ( nnode )
|
||||
|
||||
tsDLIter < SearchDest > iter ( _searchDestList.firstIter () );
|
||||
while ( iter.valid () )
|
||||
{
|
||||
ELLNODE * pnode = nnode;
|
||||
nnode = nnode->next;
|
||||
free ( pnode );
|
||||
SearchDest & curr ( *iter );
|
||||
iter++;
|
||||
delete & curr;
|
||||
}
|
||||
|
||||
epicsSocketDestroy ( this->sock );
|
||||
@@ -344,7 +355,7 @@ void udpRecvThread::run ()
|
||||
{
|
||||
epicsThreadPrivateSet ( caClientCallbackThreadId, &this->iiu );
|
||||
|
||||
if ( ellCount ( & this->iiu.dest ) == 0 ) { // X aCC 392
|
||||
if ( this->iiu._searchDestList.count () == 0 ) {
|
||||
callbackManager mgr ( this->ctxNotify, this->cbMutex );
|
||||
epicsGuard < epicsMutex > guard ( this->iiu.cacMutex );
|
||||
genLocalExcep ( mgr.cbGuard, guard,
|
||||
@@ -614,26 +625,31 @@ bool udpiiu::versionAction (
|
||||
return true;
|
||||
}
|
||||
|
||||
bool udpiiu::searchRespAction ( // X aCC 361
|
||||
const caHdr &msg,
|
||||
const osiSockAddr & addr, const epicsTime & currentTime )
|
||||
bool udpiiu :: searchRespAction (
|
||||
const caHdr & msg, const osiSockAddr & addr,
|
||||
const epicsTime & currentTime )
|
||||
{
|
||||
/*
|
||||
* we dont currently know what to do with channel's
|
||||
* found to be at non-IP type addresses
|
||||
*/
|
||||
if ( addr.sa.sa_family != AF_INET ) {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Starting with CA V4.1 the minor version number
|
||||
* is appended to the end of each search reply.
|
||||
* is appended to the end of each UDP search reply.
|
||||
* This value is ignored by earlier clients.
|
||||
*/
|
||||
ca_uint32_t minorVersion;
|
||||
if ( msg.m_postsize >= sizeof (minorVersion) ){
|
||||
if ( msg.m_postsize >= sizeof ( minorVersion ) ){
|
||||
/*
|
||||
* care is taken here not to break gcc 3.2 aggressive alias
|
||||
* analysis rules
|
||||
*/
|
||||
ca_uint8_t * pPayLoad = ( ca_uint8_t *) ( &msg + 1 );
|
||||
const ca_uint8_t * pPayLoad =
|
||||
reinterpret_cast < const ca_uint8_t *> ( & msg + 1 );
|
||||
unsigned byte0 = pPayLoad[0];
|
||||
unsigned byte1 = pPayLoad[1];
|
||||
minorVersion = ( byte0 << 8u ) | byte1;
|
||||
@@ -667,12 +683,12 @@ bool udpiiu::searchRespAction ( // X aCC 361
|
||||
}
|
||||
|
||||
if ( CA_V42 ( minorVersion ) ) {
|
||||
this->cacRef.transferChanToVirtCircuit
|
||||
cacRef.transferChanToVirtCircuit
|
||||
( msg.m_available, msg.m_cid, 0xffff,
|
||||
0, minorVersion, serverAddr, currentTime );
|
||||
}
|
||||
else {
|
||||
this->cacRef.transferChanToVirtCircuit
|
||||
cacRef.transferChanToVirtCircuit
|
||||
( msg.m_available, msg.m_cid, msg.m_dataType,
|
||||
msg.m_count, minorVersion, serverAddr, currentTime );
|
||||
}
|
||||
@@ -895,62 +911,167 @@ bool udpiiu::pushDatagramMsg ( epicsGuard < epicsMutex > & guard,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool udpiiu::datagramFlush (
|
||||
epicsGuard < epicsMutex > &, const epicsTime & /* currentTime */ )
|
||||
udpiiu :: SearchDestUDP :: SearchDestUDP (
|
||||
const osiSockAddr & destAddr, udpiiu & udpiiuIn ) :
|
||||
_destAddr ( destAddr ), _udpiiu ( udpiiuIn )
|
||||
{
|
||||
}
|
||||
|
||||
void udpiiu :: SearchDestUDP :: searchRequest (
|
||||
epicsGuard < epicsMutex > & guard, const char * pBuf, size_t bufSize )
|
||||
{
|
||||
guard.assertIdenticalMutex ( _udpiiu.cacMutex );
|
||||
assert ( bufSize <= INT_MAX );
|
||||
int bufSizeAsInt = static_cast < int > ( bufSize );
|
||||
while ( true ) {
|
||||
int status = sendto ( _udpiiu.sock, pBuf, bufSizeAsInt, 0,
|
||||
& _destAddr.sa, sizeof ( _destAddr.sa ) );
|
||||
if ( status == bufSizeAsInt ) {
|
||||
break;
|
||||
}
|
||||
if ( status >= 0 ) {
|
||||
errlogPrintf ( "CAC: UDP sendto () call returned strange xmit count?\n" );
|
||||
break;
|
||||
}
|
||||
else {
|
||||
int localErrno = SOCKERRNO;
|
||||
|
||||
if ( localErrno == SOCK_EINTR ) {
|
||||
if ( _udpiiu.shutdownCmd ) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if ( localErrno == SOCK_SHUTDOWN ) {
|
||||
break;
|
||||
}
|
||||
else if ( localErrno == SOCK_ENOTSOCK ) {
|
||||
break;
|
||||
}
|
||||
else if ( localErrno == SOCK_EBADF ) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
char buf[64];
|
||||
sockAddrToDottedIP ( &_destAddr.sa, buf, sizeof ( buf ) );
|
||||
errlogPrintf (
|
||||
"CAC: error = \"%s\" sending UDP msg to %s\n",
|
||||
sockErrBuf, buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void udpiiu :: SearchDestUDP :: show (
|
||||
epicsGuard < epicsMutex > & guard, unsigned level ) const
|
||||
{
|
||||
guard.assertIdenticalMutex ( _udpiiu.cacMutex );
|
||||
char buf[64];
|
||||
sockAddrToDottedIP ( &_destAddr.sa, buf, sizeof ( buf ) );
|
||||
:: printf ( "UDP Search destination \"%s\"\n", buf );
|
||||
}
|
||||
|
||||
udpiiu :: SearchRespCallback :: SearchRespCallback ( udpiiu & udpiiuIn ) :
|
||||
_udpiiu ( udpiiuIn )
|
||||
{
|
||||
}
|
||||
|
||||
void udpiiu :: SearchRespCallback :: notify (
|
||||
const caHdr & msg, const void * pPayloadUntyped,
|
||||
const osiSockAddr & addr, const epicsTime & currentTime )
|
||||
{
|
||||
/*
|
||||
* we dont currently know what to do with channel's
|
||||
* found to be at non-IP type addresses
|
||||
*/
|
||||
if ( addr.sa.sa_family != AF_INET ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Starting with CA V4.1 the minor version number
|
||||
* is appended to the end of each search reply.
|
||||
* This value is ignored by earlier clients.
|
||||
*/
|
||||
ca_uint32_t minorVersion;
|
||||
if ( msg.m_postsize >= sizeof ( minorVersion ) ){
|
||||
/*
|
||||
* care is taken here not to break gcc 3.2 aggressive alias
|
||||
* analysis rules
|
||||
*/
|
||||
const ca_uint8_t * pPayLoad = reinterpret_cast < const ca_uint8_t *> ( pPayloadUntyped );
|
||||
unsigned byte0 = pPayLoad[0];
|
||||
unsigned byte1 = pPayLoad[1];
|
||||
minorVersion = ( byte0 << 8u ) | byte1;
|
||||
}
|
||||
else {
|
||||
minorVersion = CA_UKN_MINOR_VERSION;
|
||||
}
|
||||
|
||||
/*
|
||||
* the type field is abused to carry the port number
|
||||
* so that we can have multiple servers on one host
|
||||
*/
|
||||
osiSockAddr serverAddr;
|
||||
serverAddr.ia.sin_family = AF_INET;
|
||||
if ( CA_V48 ( minorVersion ) ) {
|
||||
if ( msg.m_cid != INADDR_BROADCAST ) {
|
||||
serverAddr.ia.sin_addr.s_addr = htonl ( msg.m_cid );
|
||||
}
|
||||
else {
|
||||
serverAddr.ia.sin_addr = addr.ia.sin_addr;
|
||||
}
|
||||
serverAddr.ia.sin_port = htons ( msg.m_dataType );
|
||||
}
|
||||
else if ( CA_V45 (minorVersion) ) {
|
||||
serverAddr.ia.sin_port = htons ( msg.m_dataType );
|
||||
serverAddr.ia.sin_addr = addr.ia.sin_addr;
|
||||
}
|
||||
else {
|
||||
serverAddr.ia.sin_port = htons ( _udpiiu.serverPort );
|
||||
serverAddr.ia.sin_addr = addr.ia.sin_addr;
|
||||
}
|
||||
|
||||
if ( CA_V42 ( minorVersion ) ) {
|
||||
_udpiiu.cacRef.transferChanToVirtCircuit
|
||||
( msg.m_available, msg.m_cid, 0xffff,
|
||||
0, minorVersion, serverAddr, currentTime );
|
||||
}
|
||||
else {
|
||||
_udpiiu.cacRef.transferChanToVirtCircuit
|
||||
( msg.m_available, msg.m_cid, msg.m_dataType,
|
||||
msg.m_count, minorVersion, serverAddr, currentTime );
|
||||
}
|
||||
}
|
||||
|
||||
void udpiiu :: SearchRespCallback :: show (
|
||||
epicsGuard < epicsMutex > & guard, unsigned level ) const
|
||||
{
|
||||
guard.assertIdenticalMutex ( _udpiiu.cacMutex );
|
||||
::printf ( "udpiiu :: SearchRespCallback\n" );
|
||||
}
|
||||
|
||||
bool udpiiu :: datagramFlush (
|
||||
epicsGuard < epicsMutex > & guard, const epicsTime & currentTime )
|
||||
{
|
||||
guard.assertIdenticalMutex ( cacMutex );
|
||||
|
||||
// dont send the version header by itself
|
||||
if ( this->nBytesInXmitBuf <= sizeof ( caHdr ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
osiSockAddrNode *pNode = ( osiSockAddrNode * ) // X aCC 749
|
||||
ellFirst ( & this->dest );
|
||||
while ( pNode ) {
|
||||
int status;
|
||||
|
||||
assert ( this->nBytesInXmitBuf <= INT_MAX );
|
||||
status = sendto ( this->sock, this->xmitBuf,
|
||||
(int) this->nBytesInXmitBuf, 0,
|
||||
&pNode->addr.sa, sizeof ( pNode->addr.sa ) );
|
||||
if ( status != (int) this->nBytesInXmitBuf ) {
|
||||
if ( status >= 0 ) {
|
||||
errlogPrintf ( "CAC: UDP sendto () call returned strange xmit count?\n" );
|
||||
break;
|
||||
}
|
||||
else {
|
||||
int localErrno = SOCKERRNO;
|
||||
|
||||
if ( localErrno == SOCK_EINTR ) {
|
||||
if ( this->shutdownCmd ) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if ( localErrno == SOCK_SHUTDOWN ) {
|
||||
break;
|
||||
}
|
||||
else if ( localErrno == SOCK_ENOTSOCK ) {
|
||||
break;
|
||||
}
|
||||
else if ( localErrno == SOCK_EBADF ) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
char buf[64];
|
||||
sockAddrToDottedIP ( &pNode->addr.sa, buf, sizeof ( buf ) );
|
||||
errlogPrintf (
|
||||
"CAC: error = \"%s\" sending UDP msg to %s\n",
|
||||
sockErrBuf, buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
pNode = (osiSockAddrNode *) ellNext ( &pNode->node ); // X aCC 749
|
||||
tsDLIter < SearchDest > iter ( _searchDestList.firstIter () );
|
||||
while ( iter.valid () )
|
||||
{
|
||||
iter->searchRequest ( guard, this->xmitBuf, this->nBytesInXmitBuf );
|
||||
iter++;
|
||||
}
|
||||
|
||||
this->nBytesInXmitBuf = 0u;
|
||||
@@ -960,7 +1081,7 @@ bool udpiiu::datagramFlush (
|
||||
return true;
|
||||
}
|
||||
|
||||
void udpiiu::show ( unsigned level ) const
|
||||
void udpiiu :: show ( unsigned level ) const
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->cacMutex );
|
||||
|
||||
@@ -968,7 +1089,17 @@ void udpiiu::show ( unsigned level ) const
|
||||
if ( level > 1u ) {
|
||||
::printf ("\trepeater port %u\n", this->repeaterPort );
|
||||
::printf ("\tdefault server port %u\n", this->serverPort );
|
||||
printChannelAccessAddressList ( & this->dest );
|
||||
::printf ( "Search Destination List with %u items\n",
|
||||
_searchDestList.count () );
|
||||
if ( level > 2u ) {
|
||||
tsDLIterConst < SearchDest > iter (
|
||||
_searchDestList.firstIter () );
|
||||
while ( iter.valid () )
|
||||
{
|
||||
iter->show ( guard, level - 2 );
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( level > 2u ) {
|
||||
::printf ("\tsocket identifier %d\n", this->sock );
|
||||
|
||||
+37
-10
@@ -1,11 +1,11 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "searchTimer.h"
|
||||
#include "disconnectGovernorTimer.h"
|
||||
#include "repeaterSubscribeTimer.h"
|
||||
#include "SearchDest.h"
|
||||
|
||||
extern "C" void cacRecvThreadUDP ( void *pParam );
|
||||
|
||||
@@ -97,7 +98,9 @@ public:
|
||||
epicsMutex & callbackControl,
|
||||
epicsMutex & mutualExclusion,
|
||||
cacContextNotify &,
|
||||
class cac & );
|
||||
class cac &,
|
||||
unsigned port,
|
||||
tsDLList < SearchDest > & );
|
||||
virtual ~udpiiu ();
|
||||
void installNewChannel (
|
||||
epicsGuard < epicsMutex > &, nciu &, netiiu * & );
|
||||
@@ -108,17 +111,41 @@ public:
|
||||
void shutdown ( epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
void show ( unsigned level ) const;
|
||||
|
||||
|
||||
// exceptions
|
||||
class noSocket {};
|
||||
|
||||
private:
|
||||
class SearchDestUDP :
|
||||
public SearchDest {
|
||||
public:
|
||||
SearchDestUDP ( const osiSockAddr &, udpiiu & );
|
||||
void searchRequest (
|
||||
epicsGuard < epicsMutex > &, const char * pBuf, size_t bufLen );
|
||||
void show (
|
||||
epicsGuard < epicsMutex > &, unsigned level ) const;
|
||||
private:
|
||||
osiSockAddr _destAddr;
|
||||
udpiiu & _udpiiu;
|
||||
};
|
||||
class SearchRespCallback :
|
||||
public SearchDest :: Callback {
|
||||
public:
|
||||
SearchRespCallback ( udpiiu & );
|
||||
void notify (
|
||||
const caHdr &, const void * pPayload,
|
||||
const osiSockAddr &, const epicsTime & );
|
||||
void show (
|
||||
epicsGuard < epicsMutex > &, unsigned level ) const;
|
||||
private:
|
||||
udpiiu & _udpiiu;
|
||||
};
|
||||
char xmitBuf [MAX_UDP_SEND];
|
||||
char recvBuf [MAX_UDP_RECV];
|
||||
udpRecvThread recvThread;
|
||||
repeaterSubscribeTimer repeaterSubscribeTmr;
|
||||
disconnectGovernorTimer govTmr;
|
||||
ELLLIST dest;
|
||||
tsDLList < SearchDest > _searchDestList;
|
||||
double maxPeriod;
|
||||
double rtteMean;
|
||||
double rtteMeanDev;
|
||||
|
||||
+34
-11
@@ -1,12 +1,13 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
@@ -37,6 +38,7 @@
|
||||
#include "tcpRecvWatchdog.h"
|
||||
#include "tcpSendWatchdog.h"
|
||||
#include "hostNameCache.h"
|
||||
#include "SearchDest.h"
|
||||
#include "compilerDependencies.h"
|
||||
|
||||
class callbackManager;
|
||||
@@ -101,7 +103,8 @@ public:
|
||||
tcpiiu ( cac & cac, epicsMutex & mutualExclusion, epicsMutex & callbackControl,
|
||||
cacContextNotify &, double connectionTimeout, epicsTimerQueue & timerQueue,
|
||||
const osiSockAddr & addrIn, comBufMemoryManager &, unsigned minorVersion,
|
||||
ipAddrToAsciiEngine & engineIn, const cacChannel::priLev & priorityIn );
|
||||
ipAddrToAsciiEngine & engineIn, const cacChannel::priLev & priorityIn,
|
||||
const bool nameService );
|
||||
~tcpiiu ();
|
||||
void start (
|
||||
epicsGuard < epicsMutex > & );
|
||||
@@ -175,14 +178,32 @@ public:
|
||||
epicsGuard < epicsMutex > & guard, nciu & chan );
|
||||
bool connectNotify (
|
||||
epicsGuard < epicsMutex > &, nciu & chan );
|
||||
void nameResolutionMsgEndNotify ();
|
||||
|
||||
void searchRespNotify (
|
||||
const epicsTime &, const caHdrLargeArray & );
|
||||
void versionRespNotify ( const caHdrLargeArray & );
|
||||
|
||||
void * operator new ( size_t size,
|
||||
tsFreeList < class tcpiiu, 32, epicsMutexNOOP > & );
|
||||
epicsPlacementDeleteOperator (( void *,
|
||||
tsFreeList < class tcpiiu, 32, epicsMutexNOOP > & ))
|
||||
epicsPlacementDeleteOperator (( void *,
|
||||
tsFreeList < class tcpiiu, 32, epicsMutexNOOP > & ));
|
||||
|
||||
private:
|
||||
class SearchDestTCP :
|
||||
public SearchDest {
|
||||
public:
|
||||
SearchDestTCP ( tcpiiu *, cac &, const osiSockAddr & );
|
||||
void searchRequest ( epicsGuard < epicsMutex > & guard,
|
||||
const char * pbuf, size_t len );
|
||||
void show ( epicsGuard < epicsMutex > & guard, unsigned level ) const;
|
||||
void disable ();
|
||||
private:
|
||||
tcpiiu * _ptcpiiu;
|
||||
cac & _cac;
|
||||
const osiSockAddr & _addr;
|
||||
bool _active;
|
||||
};
|
||||
|
||||
hostNameCache hostNameCacheInstance;
|
||||
tcpRecvThread recvThread;
|
||||
tcpSendThread sendThread;
|
||||
@@ -205,6 +226,7 @@ private:
|
||||
comBufMemoryManager & comBufMemMgr;
|
||||
cac & cacRef;
|
||||
char * pCurData;
|
||||
SearchDestTCP * pSearchDest;
|
||||
epicsMutex & mutex;
|
||||
epicsMutex & cbMutex;
|
||||
unsigned minorProtocolVersion;
|
||||
@@ -224,6 +246,7 @@ private:
|
||||
unsigned unacknowledgedSendBytes;
|
||||
unsigned channelCountTot;
|
||||
bool _receiveThreadIsBusy;
|
||||
bool _nameService;
|
||||
bool busyStateDetected; // only modified by the recv thread
|
||||
bool flowControlActive; // only modified by the send process thread
|
||||
bool echoRequestPending;
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
# include "shareLib.h"
|
||||
#endif
|
||||
|
||||
static const unsigned char CA_MINOR_PROTOCOL_REVISION = 11;
|
||||
static const unsigned char CA_MINOR_PROTOCOL_REVISION = 12;
|
||||
|
||||
typedef ca_uint32_t caResId;
|
||||
|
||||
|
||||
@@ -1,29 +1,27 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
* 505 665 1831
|
||||
*/
|
||||
|
||||
// *must* be defined before including net_convert.h
|
||||
typedef unsigned long arrayElementCount;
|
||||
|
||||
#include "osiWireFormat.h"
|
||||
#include "net_convert.h" // byte order conversion from libca
|
||||
#include "dbMapper.h" // ait to dbr types
|
||||
#include "net_convert.h" // byte order conversion from libca
|
||||
#include "dbMapper.h" // ait to dbr types
|
||||
#include "gddAppTable.h" // EPICS application type table
|
||||
#include "gddApps.h" // gdd predefined application type codes
|
||||
#include "gddApps.h" // gdd predefined application type codes
|
||||
#include "errlog.h"
|
||||
#include "osiPoolStatus.h" // is there sufficent space in pool
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "casStrmClient.h"
|
||||
@@ -47,7 +45,7 @@ casStrmClient::pCASMsgHandler const casStrmClient::msgHandlers[] =
|
||||
& casStrmClient::readAction,
|
||||
& casStrmClient::writeAction,
|
||||
& casStrmClient::uknownMessageAction,
|
||||
& casStrmClient::uknownMessageAction,
|
||||
& casStrmClient::searchAction,
|
||||
& casStrmClient::uknownMessageAction,
|
||||
& casStrmClient::eventsOffAction,
|
||||
& casStrmClient::eventsOnAction,
|
||||
@@ -74,10 +72,13 @@ casStrmClient::pCASMsgHandler const casStrmClient::msgHandlers[] =
|
||||
//
|
||||
// casStrmClient::casStrmClient()
|
||||
//
|
||||
casStrmClient::casStrmClient ( caServerI & cas, clientBufMemoryManager & mgrIn ) :
|
||||
casStrmClient::casStrmClient (
|
||||
caServerI & cas, clientBufMemoryManager & mgrIn,
|
||||
const caNetAddr & clientAddr ) :
|
||||
casCoreClient ( cas ),
|
||||
in ( *this, mgrIn, 1 ),
|
||||
out ( *this, mgrIn ),
|
||||
_clientAddr ( clientAddr ),
|
||||
pUserName ( 0 ),
|
||||
pHostName ( 0 ),
|
||||
incommingBytesToDrain ( 0 ),
|
||||
@@ -141,7 +142,7 @@ caStatus casStrmClient :: processMsg ()
|
||||
this->incommingBytesToDrain = 0u;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// process any messages in the in buffer
|
||||
//
|
||||
@@ -618,30 +619,30 @@ caStatus casStrmClient::readNotifyAction ( epicsGuard < casClientMutex > & guard
|
||||
}
|
||||
|
||||
{
|
||||
caStatus servStat = this->read ();
|
||||
if ( servStat == S_casApp_success ) {
|
||||
caStatus servStat = this->read ();
|
||||
if ( servStat == S_casApp_success ) {
|
||||
assert ( pValueRead.valid () );
|
||||
caStatus status = this->readNotifyResponse (
|
||||
guard, pChan, *mp,
|
||||
*pValueRead, servStat );
|
||||
this->responseIsPending = ( status != S_cas_success );
|
||||
return status;
|
||||
}
|
||||
else if ( servStat == S_casApp_asyncCompletion ) {
|
||||
return S_cas_success;
|
||||
}
|
||||
else if ( servStat == S_casApp_postponeAsyncIO ) {
|
||||
}
|
||||
else if ( servStat == S_casApp_asyncCompletion ) {
|
||||
return S_cas_success;
|
||||
}
|
||||
else if ( servStat == S_casApp_postponeAsyncIO ) {
|
||||
return S_casApp_postponeAsyncIO;
|
||||
}
|
||||
else {
|
||||
caStatus status = this->readNotifyFailureResponse (
|
||||
guard, *mp, ECA_GETFAIL );
|
||||
}
|
||||
else {
|
||||
caStatus status = this->readNotifyFailureResponse (
|
||||
guard, *mp, ECA_GETFAIL );
|
||||
if ( status != S_cas_success ) {
|
||||
this->pendingResponseStatus = servStat;
|
||||
this->responseIsPending = true;
|
||||
}
|
||||
this->responseIsPending = true;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1025,23 +1026,23 @@ caStatus casStrmClient::writeAction ( epicsGuard < casClientMutex > & guard )
|
||||
//
|
||||
{
|
||||
caStatus servStat = this->write ( & casChannelI :: write );
|
||||
if ( servStat == S_casApp_success ||
|
||||
if ( servStat == S_casApp_success ||
|
||||
servStat == S_casApp_asyncCompletion ) {
|
||||
return S_cas_success;
|
||||
}
|
||||
else if ( servStat == S_casApp_postponeAsyncIO ) {
|
||||
}
|
||||
else if ( servStat == S_casApp_postponeAsyncIO ) {
|
||||
return S_casApp_postponeAsyncIO;
|
||||
}
|
||||
else {
|
||||
}
|
||||
else {
|
||||
caStatus status =
|
||||
this->writeActionSendFailureStatus ( guard, *mp,
|
||||
pChan->getCID(), servStat );
|
||||
if ( status != S_cas_success ) {
|
||||
this->pendingResponseStatus = servStat;
|
||||
this->responseIsPending = true;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@@ -1194,6 +1195,221 @@ caStatus casStrmClient::writeNotifyResponseECA_XXX (
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// casStrmClient :: asyncSearchResp()
|
||||
//
|
||||
caStatus casStrmClient :: asyncSearchResponse (
|
||||
epicsGuard < casClientMutex > & guard, const caNetAddr & /* outAddr */,
|
||||
const caHdrLargeArray & msg, const pvExistReturn & retVal,
|
||||
ca_uint16_t /* protocolRevision */, ca_uint32_t /* sequenceNumber */ )
|
||||
{
|
||||
return this->searchResponse ( guard, msg, retVal );
|
||||
}
|
||||
|
||||
// casStrmClient :: hostName()
|
||||
void casStrmClient :: hostName ( char * pInBuf, unsigned bufSizeIn ) const
|
||||
{
|
||||
_clientAddr.stringConvert ( pInBuf, bufSizeIn );
|
||||
}
|
||||
|
||||
//
|
||||
// caStatus casStrmClient :: searchResponse()
|
||||
//
|
||||
caStatus casStrmClient :: searchResponse (
|
||||
epicsGuard < casClientMutex > & guard,
|
||||
const caHdrLargeArray & msg,
|
||||
const pvExistReturn & retVal )
|
||||
{
|
||||
if ( retVal.getStatus() != pverExistsHere ) {
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
//
|
||||
// starting with V4.1 the count field is used (abused)
|
||||
// by the client to store the minor version number of
|
||||
// the client.
|
||||
//
|
||||
// Old versions expect alloc of channel in response
|
||||
// to a search request. This is no longer supported.
|
||||
//
|
||||
if ( !CA_V44( msg.m_count ) ) {
|
||||
errlogPrintf (
|
||||
"client \"%s\" using EPICS R3.11 CA "
|
||||
"connect protocol was ignored\n",
|
||||
pHostName );
|
||||
//
|
||||
// old connect protocol was dropped when the
|
||||
// new API was added to the server (they must
|
||||
// now use clients at EPICS 3.12 or higher)
|
||||
//
|
||||
caStatus status = this->sendErr (
|
||||
guard, & msg, invalidResID, ECA_DEFUNCT,
|
||||
"R3.11 connect sequence from old client was ignored" );
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// cid field is abused to carry the IP
|
||||
// address in CA_V48 or higher
|
||||
// (this allows a CA servers to serve
|
||||
// as a directory service)
|
||||
//
|
||||
// data type field is abused to carry the IP
|
||||
// port number here CA_V44 or higher
|
||||
// (this allows multiple CA servers on one
|
||||
// host)
|
||||
//
|
||||
ca_uint32_t serverAddr;
|
||||
ca_uint16_t serverPort;
|
||||
if ( CA_V48( msg.m_count ) ) {
|
||||
struct sockaddr_in ina;
|
||||
if ( retVal.addrIsValid() ) {
|
||||
caNetAddr addr = retVal.getAddr();
|
||||
ina = addr.getSockIP();
|
||||
//
|
||||
// If they dont specify a port number then the default
|
||||
// CA server port is assumed when it it is a server
|
||||
// address redirect (it is never correct to use this
|
||||
// server's port when it is a redirect).
|
||||
//
|
||||
if ( ina.sin_port == 0u ) {
|
||||
ina.sin_port = htons ( CA_SERVER_PORT );
|
||||
}
|
||||
}
|
||||
else {
|
||||
//
|
||||
// We dont fill in the servers address here because
|
||||
// the client has a tcp circuit to us and he knows
|
||||
// our address
|
||||
//
|
||||
ina.sin_addr.s_addr = htonl ( ~0U );
|
||||
ina.sin_port = htons ( 0 );
|
||||
}
|
||||
serverAddr = ntohl ( ina.sin_addr.s_addr );
|
||||
serverPort = ntohs ( ina.sin_port );
|
||||
}
|
||||
else {
|
||||
serverAddr = ntohl ( ~0U );
|
||||
serverPort = ntohs ( 0 );
|
||||
}
|
||||
|
||||
caStatus status = this->out.copyInHeader ( CA_PROTO_SEARCH,
|
||||
0, serverPort, 0, serverAddr, msg.m_available, 0 );
|
||||
//
|
||||
// Starting with CA V4.1 the minor version number
|
||||
// is appended to the end of each search reply.
|
||||
// This value is ignored by earlier clients.
|
||||
//
|
||||
if ( status == S_cas_success ) {
|
||||
this->out.commitMsg ();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// casStrmClient :: searchAction()
|
||||
//
|
||||
caStatus casStrmClient :: searchAction ( epicsGuard < casClientMutex > & guard )
|
||||
{
|
||||
const caHdrLargeArray *mp = this->ctx.getMsg();
|
||||
const char *pChanName = static_cast <char * > ( this->ctx.getData() );
|
||||
caStatus status;
|
||||
|
||||
//
|
||||
// check the sanity of the message
|
||||
//
|
||||
if ( mp->m_postsize <= 1 ) {
|
||||
caServerI::dumpMsg ( this->pHostName, "?", mp, this->ctx.getData(),
|
||||
"empty PV name extension in TCP search request?\n" );
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
if ( pChanName[0] == '\0' ) {
|
||||
caServerI::dumpMsg ( this->pHostName, "?", mp, this->ctx.getData(),
|
||||
"zero length PV name in UDP search request?\n" );
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
// check for an unterminated string before calling server tool
|
||||
// by searching backwards through the string (some early versions
|
||||
// of the client library might not be setting the pad bytes to nill)
|
||||
for ( unsigned i = mp->m_postsize-1; pChanName[i] != '\0'; i-- ) {
|
||||
if ( i <= 1 ) {
|
||||
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
|
||||
"unterminated PV name in UDP search request?\n" );
|
||||
return S_cas_success;
|
||||
}
|
||||
}
|
||||
|
||||
if ( this->getCAS().getDebugLevel() > 6u ) {
|
||||
this->hostName ( this->pHostName, sizeof ( pHostName ) );
|
||||
printf ( "\"%s\" is searching for \"%s\"\n",
|
||||
pHostName, pChanName );
|
||||
}
|
||||
|
||||
//
|
||||
// verify that we have sufficent memory for a PV and a
|
||||
// monitor prior to calling PV exist test so that when
|
||||
// the server runs out of memory we dont reply to
|
||||
// search requests, and therefore dont thrash through
|
||||
// caServer::pvExistTest() and casCreatePV::pvAttach()
|
||||
//
|
||||
if ( ! osiSufficentSpaceInPool ( 0 ) ) {
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
//
|
||||
// ask the server tool if this PV exists
|
||||
//
|
||||
this->userStartedAsyncIO = false;
|
||||
pvExistReturn pver =
|
||||
this->getCAS()->pvExistTest (
|
||||
this->ctx, _clientAddr, pChanName );
|
||||
|
||||
//
|
||||
// prevent problems when they initiate
|
||||
// async IO but dont return status
|
||||
// indicating so (and vise versa)
|
||||
//
|
||||
if ( this->userStartedAsyncIO ) {
|
||||
if ( pver.getStatus() != pverAsyncCompletion ) {
|
||||
errMessage ( S_cas_badParameter,
|
||||
"- assuming asynch IO status from caServer::pvExistTest()");
|
||||
}
|
||||
status = S_cas_success;
|
||||
}
|
||||
else {
|
||||
//
|
||||
// otherwise we assume sync IO operation was initiated
|
||||
//
|
||||
switch ( pver.getStatus() ) {
|
||||
case pverExistsHere:
|
||||
status = this->searchResponse ( guard, *mp, pver );
|
||||
break;
|
||||
|
||||
case pverDoesNotExistHere:
|
||||
status = S_cas_success;
|
||||
break;
|
||||
|
||||
case pverAsyncCompletion:
|
||||
errMessage ( S_cas_badParameter,
|
||||
"- unexpected asynch IO status from "
|
||||
"caServer::pvExistTest() ignored");
|
||||
status = S_cas_success;
|
||||
break;
|
||||
|
||||
default:
|
||||
errMessage ( S_cas_badParameter,
|
||||
"- invalid return from "
|
||||
"caServer::pvExistTest() ignored");
|
||||
status = S_cas_success;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* casStrmClient::hostNameAction()
|
||||
*/
|
||||
@@ -2610,9 +2826,8 @@ inBufClient::fillCondition casStrmClient::inBufFill ()
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
return this->in.fill ();
|
||||
}
|
||||
|
||||
bufSizeT casStrmClient ::
|
||||
inBufBytesPending () const
|
||||
|
||||
bufSizeT casStrmClient :: inBufBytesPending () const
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
return this->in.bytesPresent ();
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#ifndef casStrmClienth
|
||||
@@ -37,43 +36,44 @@ class casStrmClient :
|
||||
public casCoreClient, public outBufClient,
|
||||
public inBufClient, public tsDLNode < casStrmClient > {
|
||||
public:
|
||||
casStrmClient ( caServerI &, clientBufMemoryManager & );
|
||||
virtual ~casStrmClient();
|
||||
void show ( unsigned level ) const;
|
||||
casStrmClient ( caServerI &, clientBufMemoryManager &, const caNetAddr & clientAddr );
|
||||
virtual ~casStrmClient();
|
||||
void show ( unsigned level ) const;
|
||||
outBufClient::flushCondition flush ();
|
||||
unsigned getDebugLevel () const;
|
||||
virtual void hostName ( char * pBuf, unsigned bufSize ) const = 0;
|
||||
void userName ( char * pBuf, unsigned bufSize ) const;
|
||||
ca_uint16_t protocolRevision () const;
|
||||
unsigned getDebugLevel () const;
|
||||
void hostName ( char * pBuf, unsigned bufSize ) const;
|
||||
void userName ( char * pBuf, unsigned bufSize ) const;
|
||||
ca_uint16_t protocolRevision () const;
|
||||
void sendVersion ();
|
||||
protected:
|
||||
caStatus processMsg ();
|
||||
caStatus processMsg ();
|
||||
bool inBufFull () const;
|
||||
inBufClient::fillCondition inBufFill ();
|
||||
bufSizeT inBufBytesPending () const;
|
||||
bufSizeT outBufBytesPending () const;
|
||||
private:
|
||||
char hostNameStr [32];
|
||||
//char hostNameStr [32];
|
||||
inBuf in;
|
||||
outBuf out;
|
||||
chronIntIdResTable < casChannelI > chanTable;
|
||||
tsDLList < casChannelI > chanList;
|
||||
epicsTime lastSendTS;
|
||||
epicsTime lastRecvTS;
|
||||
char * pUserName;
|
||||
char * pHostName;
|
||||
chronIntIdResTable < casChannelI > chanTable;
|
||||
tsDLList < casChannelI > chanList;
|
||||
epicsTime lastSendTS;
|
||||
epicsTime lastRecvTS;
|
||||
caNetAddr _clientAddr;
|
||||
char * pUserName;
|
||||
char * pHostName;
|
||||
smartGDDPointer pValueRead;
|
||||
unsigned incommingBytesToDrain;
|
||||
caStatus pendingResponseStatus;
|
||||
ca_uint16_t minor_version_number;
|
||||
ca_uint16_t minor_version_number;
|
||||
bool reqPayloadNeedsByteSwap;
|
||||
bool responseIsPending;
|
||||
|
||||
caStatus createChannel ( const char * pName );
|
||||
caStatus verifyRequest ( casChannelI * & pChan );
|
||||
caStatus createChannel ( const char * pName );
|
||||
caStatus verifyRequest ( casChannelI * & pChan );
|
||||
typedef caStatus ( casStrmClient :: * pCASMsgHandler )
|
||||
( epicsGuard < casClientMutex > & );
|
||||
static pCASMsgHandler const msgHandlers[CA_PROTO_LAST_CMMD+1u];
|
||||
( epicsGuard < casClientMutex > & );
|
||||
static pCASMsgHandler const msgHandlers[CA_PROTO_LAST_CMMD+1u];
|
||||
|
||||
//
|
||||
// one function for each CA request type
|
||||
@@ -82,19 +82,20 @@ private:
|
||||
caStatus ignoreMsgAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus versionAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus echoAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus eventAddAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus eventCancelAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus readAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus readNotifyAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus writeAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus eventsOffAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus eventsOnAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus readSyncAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus clearChannelAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus claimChannelAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus writeNotifyAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus clientNameAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus hostNameAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus eventAddAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus eventCancelAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus readAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus readNotifyAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus writeAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus eventsOffAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus eventsOnAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus readSyncAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus clearChannelAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus claimChannelAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus writeNotifyAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus clientNameAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus hostNameAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus searchAction ( epicsGuard < casClientMutex > & );
|
||||
caStatus sendErr ( epicsGuard < casClientMutex > &,
|
||||
const caHdrLargeArray *curp, ca_uint32_t cid,
|
||||
const int reportedStatus, const char * pformat, ... );
|
||||
@@ -114,34 +115,40 @@ private:
|
||||
// one function for each CA request type that has
|
||||
// asynchronous completion
|
||||
//
|
||||
caStatus createChanResponse ( epicsGuard < casClientMutex > &,
|
||||
casCtx &, const pvAttachReturn & );
|
||||
caStatus readResponse ( epicsGuard < casClientMutex > &,
|
||||
casChannelI * pChan, const caHdrLargeArray & msg,
|
||||
const gdd & desc, const caStatus status );
|
||||
caStatus readNotifyResponse ( epicsGuard < casClientMutex > &,
|
||||
caStatus createChanResponse ( epicsGuard < casClientMutex > &,
|
||||
casCtx &, const pvAttachReturn & );
|
||||
caStatus readResponse ( epicsGuard < casClientMutex > &,
|
||||
casChannelI * pChan, const caHdrLargeArray & msg,
|
||||
const gdd & desc, const caStatus status );
|
||||
caStatus readNotifyResponse ( epicsGuard < casClientMutex > &,
|
||||
casChannelI *pChan, const caHdrLargeArray & msg,
|
||||
const gdd & desc, const caStatus status );
|
||||
caStatus writeResponse ( epicsGuard < casClientMutex > &, casChannelI &,
|
||||
const caHdrLargeArray & msg, const caStatus status );
|
||||
caStatus writeNotifyResponse ( epicsGuard < casClientMutex > &, casChannelI &,
|
||||
const caHdrLargeArray &, const caStatus status );
|
||||
caStatus monitorResponse ( epicsGuard < casClientMutex > &,
|
||||
const gdd & desc, const caStatus status );
|
||||
caStatus writeResponse ( epicsGuard < casClientMutex > &, casChannelI &,
|
||||
const caHdrLargeArray & msg, const caStatus status );
|
||||
caStatus writeNotifyResponse ( epicsGuard < casClientMutex > &, casChannelI &,
|
||||
const caHdrLargeArray &, const caStatus status );
|
||||
caStatus monitorResponse ( epicsGuard < casClientMutex > &,
|
||||
casChannelI & chan, const caHdrLargeArray & msg,
|
||||
const gdd &, const caStatus status );
|
||||
const gdd & desc, const caStatus status );
|
||||
caStatus enumPostponedCreateChanResponse ( epicsGuard < casClientMutex > &,
|
||||
casChannelI & chan, const caHdrLargeArray & hdr );
|
||||
caStatus privateCreateChanResponse ( epicsGuard < casClientMutex > &,
|
||||
casChannelI & chan, const caHdrLargeArray & hdr, unsigned dbrType );
|
||||
caStatus channelCreateFailedResp ( epicsGuard < casClientMutex > &,
|
||||
caStatus channelCreateFailedResp ( epicsGuard < casClientMutex > &,
|
||||
const caHdrLargeArray &, const caStatus createStatus );
|
||||
caStatus channelDestroyEventNotify (
|
||||
epicsGuard < casClientMutex > & guard,
|
||||
casChannelI * const pChan, ca_uint32_t sid );
|
||||
caStatus accessRightsResponse (
|
||||
caStatus accessRightsResponse (
|
||||
casChannelI * pciu );
|
||||
caStatus accessRightsResponse (
|
||||
caStatus accessRightsResponse (
|
||||
epicsGuard < casClientMutex > &, casChannelI * pciu );
|
||||
caStatus searchResponse (
|
||||
epicsGuard < casClientMutex > &, const caHdrLargeArray &, const pvExistReturn & );
|
||||
caStatus asyncSearchResponse (
|
||||
epicsGuard < casClientMutex > &, const caNetAddr & outAddr,
|
||||
const caHdrLargeArray & msg, const pvExistReturn & retVal,
|
||||
ca_uint16_t protocolRevision, ca_uint32_t sequenceNumber );
|
||||
|
||||
|
||||
typedef caStatus ( casChannelI :: * PWriteMethod ) (
|
||||
@@ -152,29 +159,29 @@ private:
|
||||
caStatus writeScalarData( PWriteMethod );
|
||||
|
||||
outBufClient::flushCondition xSend ( char * pBuf, bufSizeT nBytesToSend,
|
||||
bufSizeT & nBytesSent );
|
||||
bufSizeT & nBytesSent );
|
||||
inBufClient::fillCondition xRecv ( char * pBuf, bufSizeT nBytesToRecv,
|
||||
inBufClient::fillParameter parm, bufSizeT & nByesRecv );
|
||||
inBufClient::fillParameter parm, bufSizeT & nByesRecv );
|
||||
|
||||
virtual xBlockingStatus blockingState () const = 0;
|
||||
virtual xBlockingStatus blockingState () const = 0;
|
||||
|
||||
virtual outBufClient::flushCondition osdSend ( const char *pBuf, bufSizeT nBytesReq,
|
||||
bufSizeT & nBytesActual ) = 0;
|
||||
virtual inBufClient::fillCondition osdRecv ( char *pBuf, bufSizeT nBytesReq,
|
||||
bufSizeT &nBytesActual ) = 0;
|
||||
virtual outBufClient::flushCondition osdSend ( const char *pBuf, bufSizeT nBytesReq,
|
||||
bufSizeT & nBytesActual ) = 0;
|
||||
virtual inBufClient::fillCondition osdRecv ( char *pBuf, bufSizeT nBytesReq,
|
||||
bufSizeT &nBytesActual ) = 0;
|
||||
virtual void forceDisconnect () = 0;
|
||||
caStatus casMonitorCallBack (
|
||||
caStatus casMonitorCallBack (
|
||||
epicsGuard < casClientMutex > &, casMonitor &, const gdd & );
|
||||
caStatus logBadIdWithFileAndLineno (
|
||||
epicsGuard < casClientMutex > & guard, const caHdrLargeArray * mp,
|
||||
const void * dp, const int cacStatus, const char * pFileName,
|
||||
const void * dp, const int cacStatus, const char * pFileName,
|
||||
const unsigned lineno, const unsigned idIn );
|
||||
void casChannelDestroyFromInterfaceNotify ( casChannelI & chan,
|
||||
bool immediatedSestroyNeeded );
|
||||
static void issuePosponeWhenNonePendingWarning ( const char * pReqTypeStr );
|
||||
|
||||
casStrmClient ( const casStrmClient & );
|
||||
casStrmClient & operator = ( const casStrmClient & );
|
||||
casStrmClient ( const casStrmClient & );
|
||||
casStrmClient & operator = ( const casStrmClient & );
|
||||
};
|
||||
|
||||
#define logBadId(GUARD, MP, DP, CACSTAT, RESID) \
|
||||
@@ -188,4 +195,3 @@ inline ca_uint16_t casStrmClient::protocolRevision () const
|
||||
}
|
||||
|
||||
#endif // casStrmClienth
|
||||
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Author Jeff Hill
|
||||
// Author: Jeff Hill
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -35,11 +34,11 @@ const unsigned caServerConnectPendQueueSize = 5u;
|
||||
// casIntfIO::casIntfIO()
|
||||
//
|
||||
casIntfIO::casIntfIO ( const caNetAddr & addrIn ) :
|
||||
sock ( INVALID_SOCKET ),
|
||||
sock ( INVALID_SOCKET ),
|
||||
addr ( addrIn.getSockIP() )
|
||||
{
|
||||
int status;
|
||||
osiSocklen_t addrSize;
|
||||
int status;
|
||||
osiSocklen_t addrSize;
|
||||
bool portChange;
|
||||
|
||||
if ( ! osiSockAttach () ) {
|
||||
@@ -152,9 +151,9 @@ casStreamOS *casIntfIO::newStreamClient ( caServerI & cas,
|
||||
{
|
||||
static bool oneMsgFlag = false;
|
||||
|
||||
struct sockaddr newAddr;
|
||||
osiSocklen_t length = ( osiSocklen_t ) sizeof ( newAddr );
|
||||
SOCKET newSock = epicsSocketAccept ( this->sock, & newAddr, & length );
|
||||
struct sockaddr newClientAddr;
|
||||
osiSocklen_t length = ( osiSocklen_t ) sizeof ( newClientAddr );
|
||||
SOCKET newSock = epicsSocketAccept ( this->sock, & newClientAddr, & length );
|
||||
if ( newSock == INVALID_SOCKET ) {
|
||||
int errnoCpy = SOCKERRNO;
|
||||
if ( errnoCpy != SOCK_EWOULDBLOCK && ! oneMsgFlag ) {
|
||||
@@ -166,14 +165,14 @@ casStreamOS *casIntfIO::newStreamClient ( caServerI & cas,
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
else if ( sizeof ( newAddr ) > (size_t) length ) {
|
||||
else if ( sizeof ( newClientAddr ) > (size_t) length ) {
|
||||
epicsSocketDestroy ( newSock );
|
||||
errlogPrintf ( "CAS: accept returned bad address len?\n" );
|
||||
return NULL;
|
||||
}
|
||||
oneMsgFlag = false;
|
||||
ioArgsToNewStreamIO args;
|
||||
args.addr = newAddr;
|
||||
args.clientAddr = newClientAddr;
|
||||
args.sock = newSock;
|
||||
casStreamOS * pOS = new casStreamOS ( cas, bufMgr, args );
|
||||
if ( ! pOS ) {
|
||||
@@ -197,25 +196,25 @@ casStreamOS *casIntfIO::newStreamClient ( caServerI & cas,
|
||||
//
|
||||
void casIntfIO::setNonBlocking()
|
||||
{
|
||||
int status;
|
||||
osiSockIoctl_t yes = true;
|
||||
int status;
|
||||
osiSockIoctl_t yes = true;
|
||||
|
||||
status = socket_ioctl(this->sock, FIONBIO, &yes); // X aCC 392
|
||||
if ( status < 0 ) {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
errlogPrintf (
|
||||
"%s:CAS: server non blocking IO set fail because \"%s\"\n",
|
||||
__FILE__, sockErrBuf );
|
||||
}
|
||||
status = socket_ioctl(this->sock, FIONBIO, &yes); // X aCC 392
|
||||
if ( status < 0 ) {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
errlogPrintf (
|
||||
"%s:CAS: server non blocking IO set fail because \"%s\"\n",
|
||||
__FILE__, sockErrBuf );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// casIntfIO::getFD()
|
||||
//
|
||||
int casIntfIO::getFD() const
|
||||
{
|
||||
return this->sock;
|
||||
return this->sock;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -223,9 +222,9 @@ int casIntfIO::getFD() const
|
||||
//
|
||||
void casIntfIO::show(unsigned level) const
|
||||
{
|
||||
if (level>2u) {
|
||||
printf(" casIntfIO::sock = %d\n", this->sock);
|
||||
}
|
||||
if (level>2u) {
|
||||
printf(" casIntfIO::sock = %d\n", this->sock);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
//
|
||||
// $Id$
|
||||
// Author: Jeff Hill
|
||||
//
|
||||
|
||||
#include "errlog.h"
|
||||
@@ -17,11 +18,13 @@
|
||||
|
||||
// casStreamIO::casStreamIO()
|
||||
casStreamIO::casStreamIO ( caServerI & cas, clientBufMemoryManager & bufMgr,
|
||||
const ioArgsToNewStreamIO & args ) :
|
||||
casStrmClient ( cas, bufMgr ), sock ( args.sock ), addr ( args.addr),
|
||||
_osSendBufferSize ( MAX_TCP ), blockingFlag ( xIsBlocking ),
|
||||
sockHasBeenShutdown ( false )
|
||||
{
|
||||
const ioArgsToNewStreamIO & args ) :
|
||||
casStrmClient ( cas, bufMgr, args.clientAddr ),
|
||||
sock ( args.sock ),
|
||||
_osSendBufferSize ( MAX_TCP ),
|
||||
blockingFlag ( xIsBlocking ),
|
||||
sockHasBeenShutdown ( false )
|
||||
{
|
||||
assert ( sock >= 0 );
|
||||
int yes = true;
|
||||
int status;
|
||||
@@ -152,7 +155,7 @@ outBufClient::flushCondition casStreamIO::osdSend ( const char *pInBuf, bufSizeT
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
char buf[64];
|
||||
ipAddrToA (&this->addr, buf, sizeof(buf));
|
||||
this->hostName ( buf, sizeof ( buf ) );
|
||||
errlogPrintf (
|
||||
"CAS: TCP socket send to \"%s\" failed because \"%s\"\n",
|
||||
buf, sockErrBuf );
|
||||
@@ -197,7 +200,7 @@ casStreamIO::osdRecv ( char * pInBuf, bufSizeT nBytes, // X aCC 361
|
||||
myerrno != SOCK_ETIMEDOUT ) {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
ipAddrToA (&this->addr, buf, sizeof(buf));
|
||||
this->hostName ( buf, sizeof ( buf ) );
|
||||
errlogPrintf(
|
||||
"CAS: client %s disconnected because \"%s\"\n",
|
||||
buf, sockErrBuf );
|
||||
@@ -236,10 +239,8 @@ void casStreamIO::osdShow (unsigned level) const
|
||||
static_cast <const void *> ( this ) );
|
||||
if (level>1u) {
|
||||
char buf[64];
|
||||
ipAddrToA(&this->addr, buf, sizeof(buf));
|
||||
printf (
|
||||
"client=%s, port=%x\n",
|
||||
buf, ntohs(this->addr.sin_port));
|
||||
this->hostName ( buf, sizeof ( buf ) );
|
||||
printf ( "client = \"%s\"\n", buf );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,7 +287,7 @@ bufSizeT casStreamIO :: inCircuitBytesPending () const
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
char buf[64];
|
||||
ipAddrToA ( &this->addr, buf, sizeof(buf) );
|
||||
this->hostName ( buf, sizeof ( buf ) );
|
||||
errlogPrintf ("CAS: FIONREAD for %s failed because \"%s\"\n",
|
||||
buf, sockErrBuf );
|
||||
}
|
||||
@@ -300,12 +301,6 @@ bufSizeT casStreamIO :: inCircuitBytesPending () const
|
||||
}
|
||||
}
|
||||
|
||||
// casStreamIO::hostName()
|
||||
void casStreamIO::hostName ( char * pInBuf, unsigned bufSizeIn ) const
|
||||
{
|
||||
ipAddrToA ( & this->addr, pInBuf, bufSizeIn );
|
||||
}
|
||||
|
||||
// casStreamIO :: osSendBufferSize ()
|
||||
bufSizeT casStreamIO :: osSendBufferSize () const
|
||||
{
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
@@ -18,42 +18,34 @@
|
||||
#include "casStrmClient.h"
|
||||
|
||||
struct ioArgsToNewStreamIO {
|
||||
caNetAddr addr;
|
||||
SOCKET sock;
|
||||
caNetAddr clientAddr;
|
||||
SOCKET sock;
|
||||
};
|
||||
|
||||
class casStreamIO : public casStrmClient {
|
||||
public:
|
||||
casStreamIO ( caServerI &, clientBufMemoryManager &,
|
||||
casStreamIO ( caServerI &, clientBufMemoryManager &,
|
||||
const ioArgsToNewStreamIO & );
|
||||
~casStreamIO ();
|
||||
int getFD () const;
|
||||
void xSetNonBlocking ();
|
||||
const caNetAddr getAddr() const;
|
||||
void hostName ( char *pBuf, unsigned bufSize ) const;
|
||||
~casStreamIO ();
|
||||
int getFD () const;
|
||||
void xSetNonBlocking ();
|
||||
bufSizeT inCircuitBytesPending () const;
|
||||
bufSizeT osSendBufferSize () const;
|
||||
private:
|
||||
SOCKET sock;
|
||||
struct sockaddr_in addr;
|
||||
SOCKET sock;
|
||||
bufSizeT _osSendBufferSize;
|
||||
xBlockingStatus blockingFlag;
|
||||
xBlockingStatus blockingFlag;
|
||||
|
||||
bool sockHasBeenShutdown;
|
||||
xBlockingStatus blockingState() const;
|
||||
void osdShow ( unsigned level ) const;
|
||||
outBufClient::flushCondition osdSend ( const char *pBuf, bufSizeT nBytesReq,
|
||||
bufSizeT & nBytesActual );
|
||||
inBufClient::fillCondition osdRecv ( char *pBuf, bufSizeT nBytesReq,
|
||||
bufSizeT & nBytesActual );
|
||||
xBlockingStatus blockingState() const;
|
||||
void osdShow ( unsigned level ) const;
|
||||
outBufClient::flushCondition osdSend ( const char *pBuf, bufSizeT nBytesReq,
|
||||
bufSizeT & nBytesActual );
|
||||
inBufClient::fillCondition osdRecv ( char *pBuf, bufSizeT nBytesReq,
|
||||
bufSizeT & nBytesActual );
|
||||
void forceDisconnect ();
|
||||
casStreamIO ( const casStreamIO & );
|
||||
casStreamIO & operator = ( const casStreamIO & );
|
||||
casStreamIO ( const casStreamIO & );
|
||||
casStreamIO & operator = ( const casStreamIO & );
|
||||
};
|
||||
|
||||
inline const caNetAddr casStreamIO::getAddr() const
|
||||
{
|
||||
return caNetAddr ( this->addr );
|
||||
}
|
||||
|
||||
#endif // casStreamIOh
|
||||
|
||||
Vendored
+1
@@ -49,6 +49,7 @@ epicsShareExtern const ENV_PARAM EPICS_CA_REPEATER_PORT;
|
||||
epicsShareExtern const ENV_PARAM EPICS_CA_SERVER_PORT;
|
||||
epicsShareExtern const ENV_PARAM EPICS_CA_MAX_ARRAY_BYTES;
|
||||
epicsShareExtern const ENV_PARAM EPICS_CA_MAX_SEARCH_PERIOD;
|
||||
epicsShareExtern const ENV_PARAM EPICS_CA_NAME_SERVERS;
|
||||
epicsShareExtern const ENV_PARAM EPICS_CAS_INTF_ADDR_LIST;
|
||||
epicsShareExtern const ENV_PARAM EPICS_CAS_IGNORE_ADDR_LIST;
|
||||
epicsShareExtern const ENV_PARAM EPICS_CAS_AUTO_BEACON_ADDR_LIST;
|
||||
|
||||
+74
-15
@@ -1,17 +1,16 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
|
||||
/*
|
||||
* Author: Jeffrey O. Hill
|
||||
* hill@luke.lanl.gov
|
||||
* (505) 665 1831
|
||||
* Date: 5-88
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
@@ -2190,9 +2189,9 @@ int rsrv_version_reply ( struct client *client )
|
||||
}
|
||||
|
||||
/*
|
||||
* search_reply()
|
||||
* search_reply_udp ()
|
||||
*/
|
||||
static int search_reply ( caHdrLargeArray *mp, void *pPayload, struct client *client )
|
||||
static int search_reply_udp ( caHdrLargeArray *mp, void *pPayload, struct client *client )
|
||||
{
|
||||
struct dbAddr tmp_addr;
|
||||
ca_uint16_t *pMinorVersion;
|
||||
@@ -2299,6 +2298,66 @@ static int search_reply ( caHdrLargeArray *mp, void *pPayload, struct client *cl
|
||||
return RSRV_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* search_reply_tcp ()
|
||||
*/
|
||||
static int search_reply_tcp (
|
||||
caHdrLargeArray *mp, void *pPayload, struct client *client )
|
||||
{
|
||||
struct dbAddr tmp_addr;
|
||||
char *pName = (char *) pPayload;
|
||||
int status;
|
||||
int spaceAvailOnFreeList;
|
||||
size_t spaceNeeded;
|
||||
size_t reasonableMonitorSpace = 10;
|
||||
|
||||
/*
|
||||
* check the sanity of the message
|
||||
*/
|
||||
if (mp->m_postsize<=1) {
|
||||
log_header ("empty PV name in UDP search request?",
|
||||
client, mp, pPayload, 0);
|
||||
return RSRV_OK;
|
||||
}
|
||||
pName[mp->m_postsize-1] = '\0';
|
||||
|
||||
/* Exit quickly if channel not on this node */
|
||||
status = db_name_to_addr (pName, &tmp_addr);
|
||||
if (status) {
|
||||
DLOG ( 2, ( "CAS: Lookup for channel \"%s\" failed\n", pPayLoad ) );
|
||||
if (mp->m_dataType == DOREPLY)
|
||||
search_fail_reply ( mp, pPayload, client );
|
||||
return RSRV_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* stop further use of server if memory becomes scarse
|
||||
*/
|
||||
spaceAvailOnFreeList = freeListItemsAvail ( rsrvChanFreeList ) > 0
|
||||
&& freeListItemsAvail ( rsrvEventFreeList ) > reasonableMonitorSpace;
|
||||
spaceNeeded = sizeof (struct channel_in_use) +
|
||||
reasonableMonitorSpace * sizeof (struct event_ext);
|
||||
if ( ! ( osiSufficentSpaceInPool(spaceNeeded) || spaceAvailOnFreeList ) ) {
|
||||
SEND_LOCK(client);
|
||||
send_err ( mp, ECA_ALLOCMEM, client, "Server memory exhausted" );
|
||||
SEND_UNLOCK(client);
|
||||
return RSRV_OK;
|
||||
}
|
||||
|
||||
SEND_LOCK ( client );
|
||||
status = cas_copy_in_header ( client, CA_PROTO_SEARCH,
|
||||
0, ca_server_port, 0, ~0U, mp->m_available, 0 );
|
||||
if ( status != ECA_NORMAL ) {
|
||||
SEND_UNLOCK ( client );
|
||||
return RSRV_ERROR;
|
||||
}
|
||||
|
||||
cas_commit_msg ( client, 0 );
|
||||
SEND_UNLOCK ( client );
|
||||
|
||||
return RSRV_OK;
|
||||
}
|
||||
|
||||
typedef int (*pProtoStubTCP) (caHdrLargeArray *mp, void *pPayload, struct client *client);
|
||||
|
||||
/*
|
||||
@@ -2312,7 +2371,7 @@ static const pProtoStubTCP tcpJumpTable[] =
|
||||
read_action,
|
||||
write_action,
|
||||
bad_tcp_cmd_action,
|
||||
bad_tcp_cmd_action,
|
||||
search_reply_tcp,
|
||||
bad_tcp_cmd_action,
|
||||
events_off_action,
|
||||
events_on_action,
|
||||
@@ -2348,7 +2407,7 @@ static const pProtoStubUDP udpJumpTable[] =
|
||||
bad_udp_cmd_action,
|
||||
bad_udp_cmd_action,
|
||||
bad_udp_cmd_action,
|
||||
search_reply,
|
||||
search_reply_udp,
|
||||
bad_udp_cmd_action,
|
||||
bad_udp_cmd_action,
|
||||
bad_udp_cmd_action,
|
||||
|
||||
+14
-10
@@ -1,19 +1,18 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Author: Jeffrey O. Hill
|
||||
* hill@luke.lanl.gov
|
||||
* (505) 665 1831
|
||||
* Date: 5-88
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
@@ -938,6 +937,11 @@ struct client *create_tcp_client ( SOCKET sock )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* add first version message should it be needed
|
||||
*/
|
||||
rsrv_version_reply ( client );
|
||||
|
||||
if ( CASDEBUG > 0 ) {
|
||||
char buf[64];
|
||||
ipAddrToDottedIP ( &client->addr, buf, sizeof(buf) );
|
||||
|
||||
+11
-12
@@ -1,17 +1,16 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
* Author: Jeffrey O. Hill
|
||||
* hill@luke.lanl.gov
|
||||
* (505) 665 1831
|
||||
* Date: 5-88
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef INCLserverh
|
||||
@@ -29,7 +28,7 @@
|
||||
#include "asLib.h"
|
||||
#include "dbAddr.h"
|
||||
#include "dbNotify.h"
|
||||
#define CA_MINOR_PROTOCOL_REVISION 11
|
||||
#define CA_MINOR_PROTOCOL_REVISION 12
|
||||
#include "caProto.h"
|
||||
#include "ellLib.h"
|
||||
#include "epicsTime.h"
|
||||
@@ -47,7 +46,7 @@ typedef struct caHdrLargeArray {
|
||||
ca_uint32_t m_available; /* protocol stub dependent */
|
||||
ca_uint16_t m_dataType; /* operation data type */
|
||||
ca_uint16_t m_cmmd; /* operation to be performed */
|
||||
}caHdrLargeArray;
|
||||
} caHdrLargeArray;
|
||||
|
||||
/*
|
||||
* !! buf must be the first item in this structure !!
|
||||
|
||||
Reference in New Issue
Block a user