summaryrefslogtreecommitdiff
path: root/examples/C++NPv1/Logging_Client.cpp
blob: fe6f65506dd6b139459a64a1f768c15a8c59622f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*
** $Id$
**
** Copyright 2001 Addison Wesley. All Rights Reserved.
*/

#include "ace/OS_NS_sys_time.h"
#include "ace/CDR_Stream.h"
#include "ace/INET_Addr.h"
#include "ace/SOCK_Connector.h"
#include "ace/SOCK_Stream.h"
#include "ace/Log_Msg.h"
#include "ace/Log_Record.h"
#include "ace/OS_NS_unistd.h"

// FUZZ: disable check_for_streams_include
#include "ace/streams.h"

#if defined (ACE_WIN32) && (!defined (ACE_HAS_STANDARD_CPP_LIBRARY) || \
                            (ACE_HAS_STANDARD_CPP_LIBRARY == 0))
#  include <stdio.h>
#else
#  include <string>
#endif

int operator<< (ACE_OutputCDR &cdr, const ACE_Log_Record &log_record)
{
  size_t msglen = log_record.msg_data_len ();
  // The ACE_Log_Record::msg_data () function is non-const, since it
  // returns a non-const pointer to internal class members. Since we
  // know that no members are modified here, we can safely const_cast
  // the log_record parameter without violating the interface
  // contract.
  ACE_Log_Record &nonconst_record = (ACE_const_cast (ACE_Log_Record&,
                                                     log_record));
  // Insert each field from <log_record> into the output CDR stream.
  cdr << ACE_CDR::Long (log_record.type ());
  cdr << ACE_CDR::Long (log_record.pid ());
  cdr << ACE_CDR::Long (log_record.time_stamp ().sec ());
  cdr << ACE_CDR::Long (log_record.time_stamp ().usec ());
  cdr << ACE_CDR::ULong (msglen);
  cdr.write_char_array (nonconst_record.msg_data (), msglen);
  return cdr.good_bit ();
}


class Logging_Client {
private:
  ACE_SOCK_Stream logging_peer_;

public:
  ACE_SOCK_Stream &peer () { return logging_peer_; }

  int send (const ACE_Log_Record &log_record) {
    // Serialize the log record using a CDR stream, allocate
    // enough space for the complete <ACE_Log_Record>.
    const size_t max_payload_size =
     4 // type()
     + 8 // timestamp
     + 4 // process id
     + 4 // data length
     + ACE_Log_Record::MAXLOGMSGLEN // data
     + ACE_CDR::MAX_ALIGNMENT; // padding;

    // Insert contents of <log_record> into payload stream.
    ACE_OutputCDR payload (max_payload_size);
    payload << log_record;

    // Get the number of bytes used by the CDR stream.
    ACE_CDR::ULong length = payload.total_length ();

    // Send a header so the receiver can determine the byte
    // order and size of the incoming CDR stream.
    ACE_OutputCDR header (ACE_CDR::MAX_ALIGNMENT + 8);
    header << ACE_OutputCDR::from_boolean (ACE_CDR_BYTE_ORDER);

    // Store the size of the payload that follows
    header << ACE_CDR::ULong (length);
    // Use an iovec to send both buffer and payload simultaneously.
    iovec iov[2];
    iov[0].iov_base = header.begin ()->rd_ptr ();
    iov[0].iov_len  = 8;
    iov[1].iov_base = payload.begin ()->rd_ptr ();
    iov[1].iov_len  = length;

    // Send header and payload efficiently using "gather-write".
    return logging_peer_.sendv_n (iov, 2);
  }

  ~Logging_Client () { logging_peer_.close (); }
};


int main (int argc, char *argv[])
{
  u_short logger_port = argc > 1 ? atoi (argv[1]) : 0;
  const char *logger_host =
    argc > 2 ? argv[2] : ACE_DEFAULT_SERVER_HOST;
  int result;

  ACE_INET_Addr server_addr;

  if (logger_port != 0)
    result = server_addr.set (logger_port, logger_host);
  else
    result = server_addr.set ("ace_logger", logger_host);
  if (result == -1)
    ACE_ERROR_RETURN ((LM_ERROR, "lookup %s, %p\n",
                       logger_port == 0 ? "ace_logger" : argv[1],
                       logger_host), 1);

  ACE_SOCK_Connector connector;
  Logging_Client logging_client;

  if (connector.connect (logging_client.peer (), server_addr) < 0)
    ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "connect()"), 1);

#if defined (ACE_WIN32) && (!defined (ACE_HAS_STANDARD_CPP_LIBRARY) || \
                            (ACE_HAS_STANDARD_CPP_LIBRARY == 0))
  for (;;) {
    char user_input[ACE_Log_Record::MAXLOGMSGLEN];
    if (!gets (user_input))
      break;

    ACE_Time_Value now (ACE_OS::gettimeofday ());
    ACE_Log_Record log_record (LM_INFO, now, ACE_OS::getpid ());
    log_record.msg_data (user_input);
    if (logging_client.send (log_record) == -1)
      ACE_ERROR_RETURN ((LM_ERROR,
                         "%p\n", "logging_client.send()"), 1);
  }
#else

  // Limit the number of characters read on each record
  cin.width (ACE_Log_Record::MAXLOGMSGLEN);

  for (;;) {

#if defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB) && (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB == 0)
    string user_input;
    getline (cin, user_input, '\n');
#else
    std::string user_input;
    std::getline (cin, user_input, '\n');

#endif

    if (!cin || cin.eof ()) break;

    ACE_Time_Value now (ACE_OS::gettimeofday ());
    ACE_Log_Record log_record (LM_INFO, now, ACE_OS::getpid ());
    log_record.msg_data (user_input.c_str ());
    if (logging_client.send (log_record) == -1)
      ACE_ERROR_RETURN ((LM_ERROR,
                         "%p\n", "logging_client.send()"), 1);
  }
#endif

  return 0; // Logging_Client destructor closes TCP connection.
}