2 * ACE reactor demonstration
8 #include "ReadHandler.h"
10 #include <ace/streams.h>
11 #include <ace/Time_Value.h>
12 #include <ace/Log_Msg.h>
15 * This macro is used to increase the invocation counter by one when entering
16 * handle_input(). It also checks wether the counter is greater than zero
17 * indicating, that handle_input() has been called before.
19 #define INVOCATION_ENTER() do { if (mInvocationCounter > 0) \
20 ACE_ERROR((LM_ERROR, ACE_TEXT("Multiple invocations detected.\n"))); \
21 mInvocationCounter++; } while (0)
24 * THis macro is the counter part to INVOCATION_ENTER(). It decreases the
25 * invocation counter and then returns the given value. This macro is
26 * here for convenience to decrease the invocation counter also when returning
29 #define INVOCATION_RETURN(retval) do { mInvocationCounter--; \
30 return retval; } while(0)
32 ReadHandler::ReadHandler() : ACE_Event_Handler(), mStream(), mDataSize(0),
33 mData(0), mCallCounter(0), mInvocationCounter(0) {
34 ACE_TRACE("ReadHandler::ReadHandler()");
37 ReadHandler::~ReadHandler() {
38 ACE_TRACE("ReadHandler::~ReadHandler()");
40 if (mStream
.close() == -1)
41 ACE_ERROR((LM_ERROR
, ACE_TEXT("%N:%l: Failed to close socket. ")
42 ACE_TEXT ("(errno = %i: %m)\n"), ACE_ERRNO_GET
));
47 ACE_SOCK_Stream
&ReadHandler::getStream() {
48 ACE_TRACE("ReadHandler::getStream()");
52 ACE_HANDLE
ReadHandler::get_handle() const {
53 ACE_TRACE("ReadHandler::get_handle()");
54 return mStream
.get_handle();
57 int ReadHandler::handle_input(ACE_HANDLE
) {
58 ACE_TRACE("ReadHandler::handle_input(ACE_HANDLE)");
62 // the response sent to the client
65 if (mCallCounter
== 0) {
67 * This is the first request from the client.
70 // increase the call counter so the next client request goes to else-if
73 // get the desired size from the client
74 // Note: only use the sizeof and pointer to int on compatible
75 // platforms (i.e. little-endian/big-endian, data type size)
76 if (mStream
.recv_n(&mDataSize
, sizeof(mDataSize
),
77 &connTimeout
) != (ssize_t
) sizeof(mDataSize
)) {
78 ACE_ERROR((LM_ERROR
, ACE_TEXT("%N:%l: Failed to receive ")
79 ACE_TEXT ("request. (errno = %i: %m)\n"), ACE_ERRNO_GET
));
80 INVOCATION_RETURN(-1);
83 // The verbose debug output is replaced with some unintrusive dots.
84 // This increases visibility of the desired effect.
85 // ACE_DEBUG((LM_DEBUG, ACE_TEXT("%@: Data size: %i\n"), this, mDataSize));
86 ACE_DEBUG((LM_DEBUG
, ACE_TEXT(".")));
88 // check mDataSize for plausability then allocate memory
90 mData
= new (std::nothrow
) char[mDataSize
];
92 ACE_DEBUG((LM_DEBUG
, ACE_TEXT("%N:%l: Failed to allocate ")
93 ACE_TEXT ("data buffer.\n")));
98 // send the response to the client (which is still 0, if the
99 // allocation did not succeed)
100 if (mStream
.send_n(&response
, sizeof(response
), &connTimeout
) != 1) {
101 ACE_ERROR((LM_ERROR
, ACE_TEXT("%N:%l: Failed to send ")
102 ACE_TEXT ("response. (errno = %i: %m)\n"), ACE_ERRNO_GET
));
103 INVOCATION_RETURN(-1);
107 INVOCATION_RETURN(0); // get another request from the same client
109 INVOCATION_RETURN(-1); // the client will not send data if response != 'K'
111 } else if (mCallCounter
== 1) {
113 * This is the second request from the client.
116 // increase the call counter, this read handler should not be called
120 // receive the data from the client
121 if (mStream
.recv_n(mData
, mDataSize
, &connTimeout
) != mDataSize
) {
122 ACE_ERROR((LM_ERROR
, ACE_TEXT("%N:%l: Failed to receive data.")
123 ACE_TEXT ("(errno = %i: %m)\n"), ACE_ERRNO_GET
));
124 INVOCATION_RETURN(-1);
129 if (mStream
.send_n(&response
, 1, &connTimeout
) != 1) {
130 ACE_ERROR((LM_ERROR
, ACE_TEXT("%N:%l: Failed to send ")
131 ACE_TEXT ("confirmation. (errno = %i: %m)\n"), ACE_ERRNO_GET
));
132 INVOCATION_RETURN(-1);
135 INVOCATION_RETURN(-1); // ask for removal, since client does not send any more data
138 // this is to find strange actions with the call counter
139 ACE_ERROR((LM_ERROR
, ACE_TEXT("%N:%l: We should not get here.")));
140 INVOCATION_RETURN(-1);
143 int ReadHandler::handle_close(ACE_HANDLE
, ACE_Reactor_Mask
) {
144 ACE_TRACE("ReadHandler::handle_close(ACE_HANDLE, ACE_Reactor_Mask)");