1 /*
2  * %CopyrightBegin%
3  *
4  * Copyright Ericsson AB 1999-2016. All Rights Reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * %CopyrightEnd%
19  *
20  */
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <sys/types.h>
25 #include <string.h>
26 #ifdef __WIN32__
27 #include <winsock2.h>
28 #include <direct.h>
29 #include <windows.h>
30 #include <winbase.h>
31 #else /* not __WIN32__ */
32 #include <errno.h>
33 #include <unistd.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
37 #include <netdb.h>
38 #endif
39 #include "rmod_random__s.h"
40 
41 /* Used functions */
42 static int getport(int sockd);
43 static int getlisten(int port);
44 static int init(int *sd, int *portnr, int *epmd_fd);
45 void terminate(int *fd, int *sd, int *epmd_fd);
46 static void server_loop(int fd, int sd);
47 
48 /* change these, or even better, make command-line args to program... */
49 #define COOKIE "flash"
50 #define SERVER "babbis"
51 #define NODENAMESZ 512
52 #define HOSTNAMESZ 256
53 #define INBUFSZ 1024
54 #define OUTBUFSZ 1024
55 
56 
main(int argc,char ** argv)57 int main(int argc, char **argv)
58 {
59   int sd;
60   int portnr;
61   int epmd_fd;
62   ei_cnode ec;
63 
64   /* crate file descriptors */
65   if (init(&ec, &sd, &portnr, &epmd_fd) < 0)
66     return -1;
67 
68   /* start server loop */
69   server_loop(&ec, sd, epmd_fd);
70 
71   return 0;
72 }
73 
74 
75 
server_loop(ei_cnode * ec,int sd,int epmd_fd)76 static void server_loop(ei_cnode *ec, int sd, int epmd_fd)
77 {
78   ErlConnect conn;
79   erlang_msg msg;
80   int status=1;
81   CORBA_Environment *env;
82 
83   /* Create and init CORBA_Environment */
84   env = CORBA_Environment_alloc(INBUFSZ,OUTBUFSZ);
85   env->_ec = ec;
86 
87   while (status >= 0) {
88 
89     status = 1;
90 
91     if ((env->_fd = ei_accept(ec, sd, &conn)) < 0) {
92       /* error */
93       fprintf(stderr,"Accept failed: %s\n",strerror(errno));
94     }
95     else {
96       /* connection */
97       fprintf(stderr,"Accepted connection from %s\n",conn.nodename);
98 
99       while (status >= 0) {
100 
101 	/* write message to buffer */
102 	status = ei_receive_encoded(env->_fd, &env->_inbuf, &env->_inbufsz, &msg, &env->_iin);
103 	switch(status) {
104 	case ERL_SEND:
105 	case ERL_REG_SEND :
106 	  /* do transaction with fd */
107 	  rmod_random__switch(NULL,env);
108 
109 	  switch(env->_major) {
110 	  case CORBA_NO_EXCEPTION: /* Success */
111 	    break;
112 	  case CORBA_SYSTEM_EXCEPTION: /* System exception */
113 	    printf("Request failure, reason : %s\n",(char *) CORBA_exception_value(env));
114 	  CORBA_exception_free(env);
115 	  break;
116 	  default: /* Should not come here */
117 	    CORBA_exception_free(env);
118 	    break;
119 	}
120 
121 	  /* send outdata */
122 	  if (env->_iout > 0)
123 	    ei_send_encoded(env->_fd,&env->_caller,env->_outbuf,env->_iout);
124 	  break;
125 
126       case ERL_TICK :
127 	break;
128 	default : /* < 0 */
129 	  printf("Connection terminated\n");
130 	  break;
131 	}
132       }
133     }
134     status=0; /* restart */
135   }
136 
137   /* close file descriptors */
138   terminate(&env->_fd, &sd, &epmd_fd);
139 
140   /* Free env & buffers */
141   CORBA_free(env->_inbuf);
142   CORBA_free(env->_outbuf);
143   CORBA_free(env);
144 }
145 
146 
147 
init(ei_cnode * ec,int * sd,int * portnr,int * epmd_fd)148 static int init(ei_cnode *ec, int *sd, int *portnr, int *epmd_fd)
149 {
150   char host[HOSTNAMESZ];
151   char servernode[NODENAMESZ];
152   struct hostent *h;
153   int error = 0;
154 
155 #ifdef __WIN32__
156   WORD wVersionRequested;
157   WSADATA wsaData;
158 
159   wVersionRequested = MAKEWORD(1, 1);
160   if ((error = WSAStartup(wVersionRequested, &wsaData))) {
161       fprintf(stderr,"Can't initialize windows sockets: %d",error);
162   }
163 #endif
164  /* get the host name */
165   error = gethostname(host,HOSTNAMESZ);
166   if (error) {
167 #ifdef __WIN32__
168       fprintf(stderr,"can't find own hostname (error = %ld) !\n",WSAGetLastError());
169 #else /* not __WIN32__ */
170       fprintf(stderr,"can't find own hostname !\n");
171 #endif
172   }
173   else {
174     /* identify host */
175     if (!(h = ei_gethostbyname(host)))
176       fprintf(stdout,"can't find own ip address\n");
177     else {
178 
179       /* get a listen port. 0 means let system choose port number */
180       *sd = getlisten(0);
181 
182       /* what port did we get? */
183       /* this call not necessary if we specified port in call to getlisten() */
184       *portnr = getport(*sd);
185 
186       /* make the nodename server@host */
187       sprintf(servernode,"%s@%s",SERVER,host);
188 
189       /* initiate */
190       ei_init();
191 
192       /* host, alive, alive@host, addr, cookie, creation */
193       ei_connect_xinit(ec, host,SERVER,servernode,(Erl_IpAddr)(h->h_addr_list[0]),COOKIE,0);
194 
195       /* let epmd know we are here */
196       *epmd_fd = ei_publish(ec, *portnr);
197 
198       return 0;
199     }
200   }
201   return -1;
202 }
203 
204 
terminate(int * fd,int * sd,int * epmd_fd)205 void terminate(int *fd, int *sd, int *epmd_fd) {
206 
207   close(*fd);
208 
209   /* remove info from epnd */
210   close(*epmd_fd);
211 
212   /* return socket */
213   close(*sd);
214 
215 }
216 
217 
218 
219 /* tells you what port you are using on given socket */
getport(int sockd)220 static int getport(int sockd)
221 {
222   struct sockaddr_in addr;
223   int namelen = sizeof(addr);
224   int i;
225 
226   memset(&addr,0,sizeof(addr));
227 
228   if ((i = getsockname(sockd,(struct sockaddr *)&addr,&namelen))<0)
229     return i;
230 
231   return ntohs(addr.sin_port);
232 }
233 
234 
235 
236 /* return a listen socket, bound to given port */
237 /* specify port = 0 to let system assign port */
getlisten(int port)238 static int getlisten(int port)
239 {
240   int sockd;
241   struct sockaddr_in inaddr;
242   int opt = 1;
243   int i;
244 
245   /* get listen socket */
246   if ((sockd = socket(AF_INET,SOCK_STREAM,0)) < 0) return sockd;
247 
248   if ((i=setsockopt(sockd,SOL_SOCKET,SO_REUSEADDR,(void *)&opt,sizeof(opt)))<0)
249     return i;
250 
251   /* bind to requested port */
252   memset(&inaddr,0,sizeof(inaddr));
253   inaddr.sin_family = AF_INET;
254   inaddr.sin_addr.s_addr = htonl(INADDR_ANY);
255   inaddr.sin_port = htons(port);
256 
257   if ((i = bind(sockd,(struct sockaddr*) &inaddr, sizeof(inaddr))) < 0)
258     return i;
259 
260   listen(sockd,5);
261 
262   return sockd;
263 }
264 
265