1 /*
2 * %CopyrightBegin%
3 *
4 * Copyright Ericsson AB 1998-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 #include <string.h>
21 #include "eidef.h"
22 #include "eiext.h"
23 #include "eisend.h"
24 #include "eirecv.h"
25 #include "ei.h"
26 #include "ei_internal.h"
27
ei_global_register(int fd,const char * name,erlang_pid * self)28 int ei_global_register(int fd, const char *name, erlang_pid *self)
29 {
30 char buf[EISMALLBUF];
31 char *bufp=buf;
32 char tmpbuf[64];
33 int index = 0;
34 erlang_msg msg;
35 int needlink, needatom, needmonitor;
36 int arity;
37 int version;
38 int msglen;
39 int i;
40
41 /* set up rpc arguments */
42 /* { PidFrom, { call, Mod, Fun, Args, user }} */
43 index = 0;
44 if (ei_encode_version(buf,&index)
45 || ei_encode_tuple_header(buf,&index,2)
46 || ei_encode_pid(buf,&index,self) /* PidFrom */
47 || ei_encode_tuple_header(buf,&index,5)
48 || ei_encode_atom(buf,&index,"call") /* call */
49 || ei_encode_atom(buf,&index,"global") /* Mod */
50 || ei_encode_atom(buf,&index,"register_name_external")/* Fun */
51 || ei_encode_list_header(buf,&index,3) /* Args: [ name, self(), cnode ] */
52 || ei_encode_atom(buf,&index,name)
53 || ei_encode_pid(buf,&index,self)
54 || ei_encode_tuple_header(buf,&index,2)
55 || ei_encode_atom(buf,&index,"global") /* special "resolve" treatment */
56 || ei_encode_atom(buf,&index,"cnode") /* i.e. we get a SEND when conflict */
57 || ei_encode_empty_list(buf,&index)
58 || ei_encode_atom(buf,&index,"user")) { /* user */
59 EI_CONN_SAVE_ERRNO__(EINVAL);
60 return ERL_ERROR;
61 }
62
63 /* make the rpc call */
64 if (ei_send_reg_encoded(fd,self,"rex",buf,index)) return ERL_ERROR;
65
66 /* get the reply: expect link and an atom, or just an atom */
67 needlink = needatom = needmonitor = 1;
68 while (1) {
69 /* get message */
70 while (1) {
71 index = EISMALLBUF;
72 if (!(i = ei_recv_internal(fd,&bufp,&index,&msg,&msglen,1,0))) continue;
73 else break;
74 }
75
76 switch (i) {
77 case ERL_LINK:
78 /* got link */
79 if (!needlink) {
80 EI_CONN_SAVE_ERRNO__(EBADMSG);
81 return ERL_ERROR;
82 }
83 needlink = 0;
84 break;
85
86 case ERL_MONITOR_P-10:
87 /* got monitor */
88 if (!needmonitor) {
89 EI_CONN_SAVE_ERRNO__(EBADMSG);
90 return ERL_ERROR;
91 }
92 needmonitor = 0;
93 break;
94
95 case ERL_SEND:
96 /* got message - does it contain our atom? */
97 if (!needatom) {
98 EI_CONN_SAVE_ERRNO__(EBADMSG);
99 return ERL_ERROR;
100 }
101 else {
102 /* expecting { rex, yes } */
103 index = 0;
104 if (ei_decode_version(buf,&index,&version)
105 || ei_decode_tuple_header(buf,&index,&arity)
106 || (arity != 2)
107 || ei_decode_atom(buf,&index,tmpbuf)
108 || strcmp(tmpbuf,"rex")
109 || ei_decode_atom(buf,&index,tmpbuf)
110 || strcmp(tmpbuf,"yes")) {
111 EI_CONN_SAVE_ERRNO__(EBADMSG);
112 return ERL_ERROR; /* bad response from other side */
113 }
114
115 /* we're done */
116 return 0;
117 }
118 break;
119
120 default:
121 EI_CONN_SAVE_ERRNO__(EBADMSG);
122 return ERL_ERROR; /* something else */
123 }
124 }
125 return 0;
126 }
127
128