Skip to content

Instantly share code, notes, and snippets.

@mediocregopher
Last active December 15, 2015 18:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mediocregopher/5305479 to your computer and use it in GitHub Desktop.
Save mediocregopher/5305479 to your computer and use it in GitHub Desktop.
My attempt at making an erlang node
//To make gethostname be defined
#define _BSD_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include "erl-commands.h"
#define BUFSIZE 1000
int my_listen(int port);
void handle_msg(ErlMessage emsg);
extern int fd; //erlang connection
extern char * rem_name;
int main(int argc, char **argv) {
if (argc <= 4 || !strcmp(argv[1],"-h") || !strcmp(argv[1],"--help")) {
printf("\nUsage: ./redis-proxy <sname> <lport> <rem-sname> <cookie> <redis-host> <redis-port>\n\n");
printf(" sname the short name you want this c-node to connect as\n");
printf(" lport the port you want this node to listen for new erlang connections on\n");
printf(" rem-name the long name of the node you want to connect to\n");
printf(" cookie the authentication cookie\n");
return 0;
}
char * sname = argv[1];
int port = atoi(argv[2]);
rem_name = argv[3];
char * cookie = argv[4];
char hostname[50];
gethostname(hostname,50);
char full_name[50];
full_name[0] = '\0';
strncat(full_name,sname,50);
strncat(full_name,"@",50);
strncat(full_name,"127.0.0.1",50);
struct in_addr addr; /* 32-bit IP number of host */
int listen; /* Listen socket */
int fd; /* fd to Erlang node */
ErlConnect conn; /* Connection data */
erl_init(NULL, 0);
addr.s_addr = inet_addr("127.0.0.1");
fprintf(stderr, "running erl_connect_xinit\n");
if (erl_connect_xinit(hostname, sname, full_name, &addr, cookie, 0) == -1)
erl_err_quit("erl_connect_xinit");
/* Make a listen socket */
fprintf(stderr, "setting up listen\n");
if ((listen = my_listen(port)) <= 0)
erl_err_quit("my_listen");
fprintf(stderr, "publishing port\n");
if (erl_publish(port) == -1)
erl_err_quit("erl_publish");
fprintf(stderr, "accepting\n");
if ((fd = erl_accept(listen, &conn)) == ERL_ERROR)
erl_err_quit("erl_accept");
fprintf(stderr, "Connected to %s\n\r", conn.nodename);
int loop = 1;
while (loop) {
unsigned char buf[BUFSIZE];
ErlMessage emsg;
int got = erl_receive_msg(fd, buf, BUFSIZE, &emsg);
if (got == ERL_TICK) {
/* ignore */
}
else if (got == ERL_ERROR) {
loop = 0;
}
else if (emsg.type == ERL_REG_SEND) {
handle_msg(emsg);
erl_free_term(emsg.from);
erl_free_term(emsg.msg);
erl_free_term(emsg.to);
}
}
return 0;
}
int my_listen(int port) {
int listen_fd;
struct sockaddr_in addr;
int on = 1;
if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return (-1);
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
memset((void*) &addr, 0, (size_t) sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(listen_fd, (struct sockaddr*) &addr, sizeof(addr)) < 0)
return (-1);
listen(listen_fd, 5);
return listen_fd;
}
void handle_msg(ErlMessage emsg) {
if (!ERL_IS_TUPLE(emsg.msg)) return;
ETERM * _command = erl_element(1,emsg.msg);
erl_send(fd, emsg.from, _command);
erl_free_term(_command);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment