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 <compat/dcerpc.h>
21#include "echon.h"
22#include "misc.h"
23
24#ifndef _WIN32
25static void wait_for_signals(void);
26#endif
27
28/*
29 *
30 * A template DCE RPC server
31 *
32 * main() contains the basic calls needed to register an interface,
33 * get communications endpoints, and register the endpoints
34 * with the endpoint mapper.
35 *
36 * ReverseIt() implements the interface specified in echo.idl
37 *
38 */
39
40
41int main(int ac ATTRIBUTE_UNUSED, char *av[] ATTRIBUTE_UNUSED)
42{
43  unsigned32 status;
44  rpc_binding_vector_p_t     server_binding;
45  char * string_binding;
46  unsigned32 i;
47
48  /*
49   * Register the Interface with the local endpoint mapper (rpcd)
50   */
51
52  printf ("Registering server.... \n");
53  rpc_server_register_if(echon_v1_0_s_ifspec,
54			 NULL,
55			 NULL,
56			 &status);
57      chk_dce_err(status, "rpc_server_register_if()", "", 1);
58
59      printf("registered.\nPreparing binding handle...\n");
60
61      rpc_server_use_protseq((unsigned_char_p_t)"ncacn_ip_tcp",
62	      rpc_c_protseq_max_calls_default, &status);
63
64      chk_dce_err(status, "rpc_server_use_all_protseqs()", "", 1);
65      rpc_server_inq_bindings(&server_binding, &status);
66      chk_dce_err(status, "rpc_server_inq_bindings()", "", 1);
67
68      /*
69       * Register bindings with the endpoint mapper
70       */
71
72	printf("registering bindings with endpoint mapper\n");
73
74  rpc_ep_register(echon_v1_0_s_ifspec,
75		  server_binding,
76		  NULL,
77		  (unsigned char *)"QDA application server",
78		  &status);
79      chk_dce_err(status, "rpc_ep_register()", "", 1);
80
81	printf("registered.\n");
82
83      /*
84       * Print out the servers endpoints (TCP and UDP port numbers)
85       */
86
87  printf ("Server's communications endpoints are:\n");
88
89    for (i=0; i<RPC_FIELD_COUNT(server_binding); i++)
90    {
91        rpc_binding_to_string_binding(RPC_FIELD_BINDING_H(server_binding)[i],
92				    (unsigned char **)&string_binding,
93				    &status
94				    );
95      if (string_binding)
96		printf("\t%s\n",string_binding);
97    }
98
99
100#ifndef _WIN32
101  /*
102   * Start the signal waiting thread in background. This thread will
103   * Catch SIGINT and gracefully shutdown the server.
104   */
105
106  wait_for_signals();
107#endif
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#ifndef _WIN32
133    /*
134     * Kill the signal handling thread
135     */
136
137#endif
138
139  printf ("Unregistering server from the endpoint mapper.... \n");
140  rpc_ep_unregister(echon_v1_0_s_ifspec,
141		    server_binding,
142		    NULL,
143		    &status);
144  chk_dce_err(status, "rpc_ep_unregister()", "", 0);
145
146  /*
147   * retire the binding information
148   */
149
150  printf("Cleaning up communications endpoints... \n");
151  rpc_server_unregister_if(echon_v1_0_s_ifspec,
152			   NULL,
153			   &status);
154  chk_dce_err(status, "rpc_server_unregister_if()", "", 0);
155
156  exit(0);
157
158}
159
160
161/*=========================================================================
162 *
163 * Server implementation of ReverseIt()
164 *
165 *=========================================================================*/
166
167idl_boolean
168ReplyBack(h, in_num, out_num, status)
169     rpc_binding_handle_t h;
170     unsigned32 in_num;
171     unsigned32* out_num;
172     error_status_t * status;
173{
174
175  char * binding_info;
176  error_status_t e;
177
178  /*
179   * Get some info about the client binding
180   */
181
182  rpc_binding_to_string_binding(h, (unsigned char **)&binding_info, &e);
183  if (e == rpc_s_ok)
184    {
185      printf ("ReplyBack() called by client: %s\n", binding_info);
186    }
187
188  printf("\n\nFunction ReplyBack() -- input argments\n");
189
190  printf("\tin_num = %ld\n", (long)in_num);
191
192  printf ("\n=========================================\n");
193
194  *out_num = in_num;
195  *status = error_status_ok;
196
197  return 1;
198
199}
200
201
202#ifndef _WIN32
203/*=========================================================================
204 *
205 * wait_for_signals()
206 *
207 *
208 * Set up the process environment to properly deal with signals.
209 * By default, we isolate all threads from receiving asynchronous
210 * signals. We create a thread that handles all async signals.
211 * The signal handling actions are handled in the handler thread.
212 *
213 * For AIX, we cant use a thread that sigwaits() on a specific signal,
214 * we use a plain old, lame old Unix signal handler.
215 *
216 *=========================================================================*/
217
218
219void
220wait_for_signals(void)
221{
222    sigset_t signals;
223
224    sigemptyset(&signals);
225    sigaddset(&signals, SIGINT);
226
227    dcethread_signal_to_interrupt(&signals, dcethread_self());
228}
229
230#endif
231