Merge branch 'pu'
[jungerl.git] / lib / gtkNode / src / gtkNode_cnode.c
blob658fa509c7f3bd135c0859e6f65e549eb62562c7
1 #include <string.h>
2 #include "gtkNode.h"
4 #define CREATION 1
5 #define REMNODE argv[1]
6 #define REMHOST argv[2]
7 #define REMREG argv[3]
8 #define COOKIE argv[4]
9 #define NODE_NAME argv[5]
10 #define ERL_DIST_VSN atoi(argv[6])
12 static int fd; /* fd to remote Erlang node */
13 static gchar* rem_regname; /* process name on remote Erlang node */
15 int gn_start_cnode(char **argv) {
16 extern ei_cnode ec;
17 char rem_node_name[MAXATOMLEN] = ""; /* other node name */
18 ei_x_buff xbuf;
19 erlang_pid *self = ei_self(&ec);
21 strcat(rem_node_name,REMNODE);
22 strcat(rem_node_name,"@");
23 strcat(rem_node_name,REMHOST);
24 rem_regname = g_strdup(REMREG);
25 g_print("I am %s, you are %s\n", NODE_NAME, rem_node_name);
27 ei_set_compat_rel(ERL_DIST_VSN); /* erlnode version of dist. protocol */
29 if ( ei_connect_init(&ec, NODE_NAME, COOKIE, CREATION) < 0 )
30 g_critical("ei_connect_init");
32 if ( (fd = ei_connect(&ec, rem_node_name)) < 0 )
33 g_critical("ei_connect failed.\nwrong cookie? erl-dist version mismatch?");
35 self->num = fd; /* bug?? in ei_reg_send_tmo */
37 ei_x_new_with_version(&xbuf);
38 gn_wrap_ans("handshake", &xbuf);
39 ei_x_encode_empty_list(&xbuf);
40 gn_send(&xbuf);
41 ei_x_free(&xbuf);
43 return fd;
46 void gn_send(ei_x_buff *xbuf) {
47 extern ei_cnode ec;
49 if ( ei_reg_send(&ec, fd, rem_regname, xbuf->buff, xbuf->index) )
50 g_critical("bad send");
53 static gboolean get_fpointer(char *cmd, ei_x_buff *xbuf, gpointer* poi) {
54 extern GModule* gmod;
56 if ( ! g_module_supported() ) g_critical("gtkNode requires working gmodule");
58 if ( ! gmod ) gmod = g_module_open(NULL,0); /* "gtkNode_gtk.so" */
60 if ( g_module_symbol(gmod, cmd, poi) ) return TRUE;
62 g_warning("could not find '%s'.", cmd);
63 gn_enc_2_error(xbuf, "no_such_function");
64 ei_x_encode_atom(xbuf, cmd);
65 return FALSE;
68 static gboolean make_reply(ei_x_buff *xbuf, char *buff, int *index) {
69 int k;
70 gint arity;
71 gchar cmd[MAXATOMLEN+1];
72 gboolean (*funcp)(int, ei_x_buff *, char *, int *);
74 if ( ! ((arity = gn_get_tuple(xbuf, buff, index)) > -1) ||
75 ! gn_check_arity(xbuf,2,arity) ||
76 ! gn_get_arg_gchar_fix(xbuf, buff, index, cmd) ||
77 ! ((arity = gn_get_list(xbuf, buff, index)) > -1) )
78 return FALSE;
80 if ( get_fpointer(cmd, xbuf, (gpointer *)&funcp) &&
81 (*funcp)(arity, xbuf, buff, index) ) {
82 g_assert( ei_decode_list_header(buff,index,&k) == 0 );
83 g_assert( k == 0 );
84 return TRUE;
87 return FALSE;
90 static void make_reply_list(ei_x_buff *xbuf, char *buff, int *index) {
92 gint arity, i;
94 if ( ! ((arity = gn_get_list(xbuf, buff, index)) > -1) )
95 return;
97 gn_wrap_ans("reply",xbuf);
98 for (i = 0; i < arity; i++) {
99 ei_x_encode_list_header(xbuf, 1);
100 if ( ! make_reply(xbuf, buff, index) )
101 break;
103 ei_x_encode_empty_list(xbuf);
107 static void reply(erlang_msg *msg, ei_x_buff *recv_x_buf) {
108 int i = 0;
109 int version;
110 ei_x_buff xbuf;
112 ei_decode_version(recv_x_buf->buff, &i, &version);
113 ei_x_new_with_version(&xbuf);
114 make_reply_list(&xbuf, recv_x_buf->buff, &i);
115 gn_send(&xbuf);
116 ei_x_free(&xbuf);
119 /* called from gtk main loop when there's data on the cnode socket */
120 gboolean gn_handle_read(GIOChannel *source,GIOCondition cond,gpointer data){
121 erlang_msg msg;
122 ei_x_buff xbuf;
124 /* fd = g_io_channel_unix_get_fd(source); */
125 ei_x_new_with_version(&xbuf);
126 switch ( ei_xreceive_msg(fd, &msg, &xbuf) ){
127 case ERL_TICK:
128 break; /* ignore */
129 case ERL_MSG:
130 switch (msg.msgtype) {
131 case ERL_SEND:
132 case ERL_REG_SEND:
133 reply(&msg, &xbuf);
134 break;
135 case ERL_LINK:
136 case ERL_UNLINK:
137 case ERL_GROUP_LEADER:
138 break; /* ignore */
139 case ERL_EXIT:
140 case ERL_EXIT2:
141 case ERL_NODE_LINK:
142 gtk_main_quit(); /* crash and burn */
143 return FALSE;
145 break;
146 case ERL_ERROR:
147 gtk_main_quit(); /* crash and burn */
148 return FALSE;
150 ei_x_free(&xbuf);
151 return TRUE;