/*
* %CopyrightBegin%
*
* Copyright Ericsson AB 1999-2009. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* %CopyrightEnd%
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#ifdef __WIN32__
#include <winsock2.h>
#include <direct.h>
#include <windows.h>
#include <winbase.h>
#else /* not __WIN32__ */
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#endif
#include "rmod_random__s.h"
/* Used functions */
static int getport(int sockd);
static int getlisten(int port);
static int init(int *sd, int *portnr, int *epmd_fd);
void terminate(int *fd, int *sd, int *epmd_fd);
static void server_loop(int fd, int sd);
/* change these, or even better, make command-line args to program... */
#define COOKIE "flash"
#define SERVER "babbis"
#define NODENAMESZ 512
#define HOSTNAMESZ 256
#define INBUFSZ 1024
#define OUTBUFSZ 1024
int main(int argc, char **argv)
{
int sd;
int portnr;
int epmd_fd;
/* crate file descriptors */
if (init(&sd, &portnr, &epmd_fd) < 0)
return -1;
/* start server loop */
server_loop(sd,epmd_fd);
return 0;
}
static void server_loop(int sd, int epmd_fd)
{
ErlConnect conn;
erlang_msg msg;
int status=1;
CORBA_Environment *env;
/* Create and init CORBA_Environment */
env = CORBA_Environment_alloc(INBUFSZ,OUTBUFSZ);
while (status >= 0) {
status = 1;
if ((env->_fd = erl_accept(sd,&conn)) < 0) {
/* error */
fprintf(stderr,"Accept failed: %s\n",strerror(errno));
}
else {
/* connection */
fprintf(stderr,"Accepted connection from %s\n",conn.nodename);
while (status >= 0) {
/* write message to buffer */
status = ei_receive_encoded(env->_fd, &env->_inbuf, &env->_inbufsz, &msg, &env->_iin);
switch(status) {
case ERL_SEND:
case ERL_REG_SEND :
/* do transaction with fd */
rmod_random__switch(NULL,env);
switch(env->_major) {
case CORBA_NO_EXCEPTION: /* Success */
break;
case CORBA_SYSTEM_EXCEPTION: /* System exception */
printf("Request failure, reason : %s\n",(char *) CORBA_exception_value(env));
CORBA_exception_free(env);
break;
default: /* Should not come here */
CORBA_exception_free(env);
break;
}
/* send outdata */
if (env->_iout > 0)
ei_send_encoded(env->_fd,&env->_caller,env->_outbuf,env->_iout);
break;
case ERL_TICK :
break;
default : /* < 0 */
printf("Connection terminated\n");
break;
}
}
}
status=0; /* restart */
}
/* close file descriptors */
terminate(&env->_fd, &sd, &epmd_fd);
/* Free env & buffers */
CORBA_free(env->_inbuf);
CORBA_free(env->_outbuf);
CORBA_free(env);
}
static int init(int *sd, int *portnr, int *epmd_fd)
{
char host[HOSTNAMESZ];
char servernode[NODENAMESZ];
struct hostent *h;
int error = 0;
#ifdef __WIN32__
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(1, 1);
if ((error = WSAStartup(wVersionRequested, &wsaData))) {
fprintf(stderr,"Can't initialize windows sockets: %d",error);
}
#endif
/* get the host name */
error = gethostname(host,HOSTNAMESZ);
if (error) {
#ifdef __WIN32__
fprintf(stderr,"can't find own hostname (error = %ld) !\n",WSAGetLastError());
#else /* not __WIN32__ */
fprintf(stderr,"can't find own hostname !\n");
#endif
}
else {
/* identify host */
if (!(h = erl_gethostbyname(host)))
fprintf(stdout,"can't find own ip address\n");
else {
/* get a listen port. 0 means let system choose port number */
*sd = getlisten(0);
/* what port did we get? */
/* this call not necessary if we specified port in call to getlisten() */
*portnr = getport(*sd);
/* make the nodename server@host */
sprintf(servernode,"%s@%s",SERVER,host);
/* initiate */
erl_init(NULL,0);
/* host, alive, alive@host, addr, cookie, creation */
erl_connect_xinit(host,SERVER,servernode,(Erl_IpAddr)(h->h_addr_list[0]),COOKIE,0);
/* let epmd know we are here */
*epmd_fd = erl_publish(*portnr);
return 0;
}
}
return -1;
}
void terminate(int *fd, int *sd, int *epmd_fd) {
close(*fd);
/* remove info from epnd */
close(*epmd_fd);
/* return socket */
close(*sd);
}
/* tells you what port you are using on given socket */
static int getport(int sockd)
{
struct sockaddr_in addr;
int namelen = sizeof(addr);
int i;
memset(&addr,0,sizeof(addr));
if ((i = getsockname(sockd,(struct sockaddr *)&addr,&namelen))<0)
return i;
return ntohs(addr.sin_port);
}
/* return a listen socket, bound to given port */
/* specify port = 0 to let system assign port */
static int getlisten(int port)
{
int sockd;
struct sockaddr_in inaddr;
int opt = 1;
int i;
/* get listen socket */
if ((sockd = socket(AF_INET,SOCK_STREAM,0)) < 0) return sockd;
if ((i=setsockopt(sockd,SOL_SOCKET,SO_REUSEADDR,(void *)&opt,sizeof(opt)))<0)
return i;
/* bind to requested port */
memset(&inaddr,0,sizeof(inaddr));
inaddr.sin_family = AF_INET;
inaddr.sin_addr.s_addr = htonl(INADDR_ANY);
inaddr.sin_port = htons(port);
if ((i = bind(sockd,(struct sockaddr*) &inaddr, sizeof(inaddr))) < 0)
return i;
listen(sockd,5);
return sockd;
}