1/*
2 * echo_server      : demo DCE RPC application
3 *
4 * Jim Doyle, jrd@bu.edu  09-05-1998
5 *
6 *
7 */
8#if HAVE_CONFIG_H
9#include <config.h>
10#endif
11
12#ifndef _POSIX_PTHREAD_SEMANTICS
13#define _POSIX_PTHREAD_SEMANTICS 1
14#endif
15
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <signal.h>
20#include <ctype.h>
21#include <dce/rpc.h>
22#define DCETHREAD_CHECKED
23#define DCETHREAD_USE_THROW
24#include <dce/dcethread.h>
25#include "echou.h"
26#include "misc.h"
27
28static void wait_for_signals(void);
29
30/*
31 *
32 * A template DCE RPC server
33 *
34 * main() contains the basic calls needed to register an interface,
35 * get communications endpoints, and register the endpoints
36 * with the endpoint mapper.
37 *
38 * ReverseIt() implements the interface specified in echo.idl
39 *
40 */
41
42
43int main(int ac ATTRIBUTE_UNUSED, char *av[] ATTRIBUTE_UNUSED)
44{
45  unsigned32 status;
46  rpc_binding_vector_p_t     server_binding;
47  char * string_binding;
48  unsigned32 i;
49
50  /*
51   * Register the Interface with the local endpoint mapper (rpcd)
52   */
53
54  printf ("Registering server.... \n");
55  rpc_server_register_if(echou_v1_0_s_ifspec,
56			 NULL,
57			 NULL,
58			 &status);
59      chk_dce_err(status, "rpc_server_register_if()", "", 1);
60
61      printf("registered.\nPreparing binding handle...\n");
62
63      rpc_server_use_protseq((unsigned_char_p_t)"ncacn_ip_tcp",
64	      rpc_c_protseq_max_calls_default, &status);
65
66      chk_dce_err(status, "rpc_server_use_all_protseqs()", "", 1);
67      rpc_server_inq_bindings(&server_binding, &status);
68      chk_dce_err(status, "rpc_server_inq_bindings()", "", 1);
69
70      /*
71       * Register bindings with the endpoint mapper
72       */
73
74	printf("registering bindings with endpoint mapper\n");
75
76  rpc_ep_register(echou_v1_0_s_ifspec,
77		  server_binding,
78		  NULL,
79		  (unsigned char *)"QDA application server",
80		  &status);
81      chk_dce_err(status, "rpc_ep_register()", "", 1);
82
83	printf("registered.\n");
84
85      /*
86       * Print out the servers endpoints (TCP and UDP port numbers)
87       */
88
89  printf ("Server's communications endpoints are:\n");
90
91  for (i=0; i<server_binding->count; i++)
92    {
93      rpc_binding_to_string_binding(server_binding->binding_h[i],
94				    (unsigned char **)&string_binding,
95				    &status
96				    );
97      if (string_binding)
98		printf("\t%s\n",string_binding);
99    }
100
101
102  /*
103   * Start the signal waiting thread in background. This thread will
104   * Catch SIGINT and gracefully shutdown the server.
105   */
106
107  wait_for_signals();
108
109  /*
110   * Begin listening for calls
111   */
112
113  printf ("listening for calls.... \n");
114
115  DCETHREAD_TRY
116    {
117      rpc_server_listen(rpc_c_listen_max_calls_default, &status);
118    }
119  DCETHREAD_CATCH_ALL(THIS_CATCH)
120    {
121      printf ("Server stoppped listening\n");
122    }
123  DCETHREAD_ENDTRY
124
125    /*
126     * If we reached this point, then the server was stopped, most likely
127     * by the signal handler thread called rpc_mgmt_stop_server().
128     * gracefully cleanup and unregister the bindings from the
129     * endpoint mapper.
130     */
131
132    /*
133     * Kill the signal handling thread
134     */
135
136  printf ("Unregistering server from the endpoint mapper.... \n");
137  rpc_ep_unregister(echou_v1_0_s_ifspec,
138		    server_binding,
139		    NULL,
140		    &status);
141  chk_dce_err(status, "rpc_ep_unregister()", "", 0);
142
143  /*
144   * retire the binding information
145   */
146
147  printf("Cleaning up communications endpoints... \n");
148  rpc_server_unregister_if(echou_v1_0_s_ifspec,
149			   NULL,
150			   &status);
151  chk_dce_err(status, "rpc_server_unregister_if()", "", 0);
152
153  exit(0);
154
155}
156
157
158/*=========================================================================
159 *
160 * Server implementation of ReverseIt()
161 *
162 *=========================================================================*/
163
164idl_boolean
165ReplyBack(h, in_type, in_value, out_value, status)
166     rpc_binding_handle_t h;
167     idl_long_int in_type;
168     EchoUnion *in_value;
169     EchoUnion **out_value;
170     error_status_t * status;
171{
172
173  char * binding_info;
174  error_status_t e;
175  *out_value = (EchoUnion*) rpc_ss_allocate(sizeof(EchoUnion));
176
177  /*
178   * Get some info about the client binding
179   */
180
181  rpc_binding_to_string_binding(h, (unsigned char **)&binding_info, &e);
182  if (e == rpc_s_ok)
183    {
184      printf ("ReplyBack() called by client: %s\n", binding_info);
185    }
186
187  printf("\n\nFunction ReplyBack() -- input argments\n");
188
189  if (in_value == NULL)
190  {
191      printf("in_value = [null]\n");
192      *out_value = NULL;
193  }
194  else if (in_type == 1)
195  {
196      printf("in_value = [int] %li\n", (long int) in_value->integer);
197      (*out_value)->integer = -in_value->integer;
198  }
199  else if (in_type == 2)
200  {
201      printf("in_value = [float] %f\n", (double) in_value->fp);
202      (*out_value)->fp = -in_value->fp;
203  }
204  else if (in_type == 3)
205  {
206      int i, len;
207      printf("in_value = [string] %s\n", (char*) in_value->str);
208      len = strlen((const char *)in_value->str);
209      (*out_value)->str = rpc_ss_allocate(sizeof(*in_value->str) * (len+1));
210
211      for (i = 0; i < len; i++)
212      {
213          (*out_value)->str[i] = in_value->str[len-1-i];
214      }
215
216      (*out_value)->str[len] = 0;
217  }
218
219  printf ("\n=========================================\n");
220
221  //*out_value = NULL;
222  *status = error_status_ok;
223
224  return 1;
225}
226
227
228/*=========================================================================
229 *
230 * wait_for_signals()
231 *
232 *
233 * Set up the process environment to properly deal with signals.
234 * By default, we isolate all threads from receiving asynchronous
235 * signals. We create a thread that handles all async signals.
236 * The signal handling actions are handled in the handler thread.
237 *
238 * For AIX, we cant use a thread that sigwaits() on a specific signal,
239 * we use a plain old, lame old Unix signal handler.
240 *
241 *=========================================================================*/
242
243
244void
245wait_for_signals(void)
246{
247    sigset_t signals;
248
249    sigemptyset(&signals);
250    sigaddset(&signals, SIGINT);
251
252    dcethread_signal_to_interrupt(&signals, dcethread_self());
253}
254