Merged Codeathon 2008 changes (10292..10293 on cvs-trunk branch).

* Fixed conflicts until base compiles
 * COMPLETELY UNTESTED
This commit is contained in:
Ralph Lange
2010-04-06 17:59:35 -04:00
parent 6518adf901
commit 23612a7afe
23 changed files with 1244 additions and 596 deletions
+8 -12
View File
@@ -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
View File
@@ -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 fr 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 fr 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">subscribefor 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 &gt; 5000</td>
<td>i&gt; 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 implementedusing 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 numbersbecause 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 &gt; 5000</td>
<td>i&gt; 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 &gt; 0.1 seconds</td>
<td>r&gt; 0.1 seconds</td>
<td>EPICS_CA_BEACON_PERIOD</td>
</tr>
<tr>
<td>EPICS_CAS_BEACON_PORT</td>
<td>i &gt; 5000</td>
<td>i&gt; 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 &lt;sec&gt;</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 &lt;prio&gt;</td>
@@ -1115,7 +1115,7 @@ the output.</p>
</tr>
<tr>
<td>-d &lt;type&gt;</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 &lt;sec&gt;</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 &lt;mask&gt;</td>
@@ -1495,7 +1495,7 @@ command line is used.</p>
</tr>
<tr>
<td>-w &lt;sec&gt;</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 &lt;sec&gt;</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 &lt;level&gt;</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&rsquo;t allowed to grow to an infinite size. This is a law of nature
&ndash; 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&rsquo;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, thenan 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 theprocess variable's maximumnative element count may
be requested. The process variable'smaximum 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'scall 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 &minus; 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&rsquo;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&rsquo;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'schannel 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 onlyenter
aconnected 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 "&lt;record
name&gt;.&lt;field name&gt;". 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 resourcesassociated 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) registeredwith thechannel.</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 suppliedcallback 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 callbackfunction</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 theserver 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>Flushoutstanding IO requests to the server.This routine might be useful
touserswho needto flush requestsprior toperforming 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 createdno 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 bea member of theset 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>Themaximum 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>Returnsboolean trueif the client currently has read access to the
specified channel andboolean falseotherwise.</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 trueif the client currently has read access to the specified
channel andboolean falseotherwise</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>Returnsboolean trueif the client currently haswrite access to the
specified channel andboolean falseotherwise.</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 withCOUNT 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 &lt;cadef.h&gt;
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>channelidentifier</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>
+36
View File
@@ -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
View File
@@ -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
+8 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+1 -1
View File
@@ -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;
+256 -41
View File
@@ -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 ();
+75 -69
View File
@@ -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
+32 -33
View File
@@ -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);
}
}
//
+20 -25
View File
@@ -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
{
+24 -32
View File
@@ -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
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 !!