1 /*
2  * %CopyrightBegin%
3  *
4  * Copyright Ericsson AB 1998-2020. 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 #ifdef __WIN32__
21 #include <winsock2.h>
22 #include <windows.h>
23 #include <winbase.h>
24 
25 #else /* unix */
26 #include <sys/types.h>
27 #include <unistd.h>
28 #include <sys/uio.h>
29 #endif
30 
31 #include <stdio.h>
32 
33 #include "eidef.h"
34 #include "eiext.h"
35 #include "eisend.h"
36 #include "putget.h"
37 #include "ei_connect_int.h"
38 #include "ei_internal.h"
39 #include "ei_trace.h"
40 #include "ei_portio.h"
41 #include "show_msg.h"
42 
ei_send_reg_encoded_tmo(int fd,const erlang_pid * from,const char * to,char * msg,int msglen,unsigned ms)43 int ei_send_reg_encoded_tmo(int fd, const erlang_pid *from,
44 			    const char *to, char *msg, int msglen,
45 			    unsigned ms)
46 {
47     char *s, header[1400]; /* see size calculation below */
48     erlang_trace *token = NULL;
49     int index = 5; /* reserve 5 bytes for control message */
50     int err;
51     ei_socket_callbacks *cbs;
52     void *ctx;
53     ssize_t len, tot_len;
54     unsigned tmo = ms == 0 ? EI_SCLBK_INF_TMO : ms;
55 
56     err = EI_GET_CBS_CTX__(&cbs, &ctx, fd);
57     if (err) {
58         EI_CONN_SAVE_ERRNO__(err);
59         return ERL_ERROR;
60     }
61 
62     /* are we tracing? */
63     /* check that he can receive trace tokens first */
64     if (ei_distversion(fd) > 0)
65 	token = ei_trace(0,NULL);
66 
67     EI_CONN_SAVE_ERRNO__(EINVAL);
68 
69     /* header = REG_SEND, from, cookie, toname         max sizes: */
70     if (ei_encode_version(header,&index) < 0)                   /*   1 */
71         return ERL_ERROR;
72     if (token) {
73 	if (ei_encode_tuple_header(header,&index,5) < 0)        /*   2 */
74             return ERL_ERROR;
75 	if (ei_encode_long(header,&index,ERL_REG_SEND_TT) < 0)  /*   2 */
76             return ERL_ERROR;
77     } else {
78 	if (ei_encode_tuple_header(header,&index,4) < 0)
79             return ERL_ERROR;
80 	if (ei_encode_long(header,&index,ERL_REG_SEND) < 0)
81             return ERL_ERROR;
82     }
83     if (ei_encode_pid(header, &index, from) < 0)                /* 268 */
84         return ERL_ERROR;
85     if (ei_encode_atom(header, &index, ei_getfdcookie(fd)) < 0) /* 258 */
86         return ERL_ERROR;
87     if (ei_encode_atom(header, &index, to) < 0)                 /* 268 */
88         return ERL_ERROR;
89 
90     if (token) {
91         if (ei_encode_trace(header,&index,token) < 0)      /* 534 */
92             return ERL_ERROR;
93     }
94     /* control message (precedes header actually) */
95     /* length = 1 ('p') + header len + message len */
96     s = header;
97     put32be(s, index + msglen - 4);                       /*   4 */
98     put8(s, ERL_PASS_THROUGH);                                /*   1 */
99                                                 /*** sum: 1336 */
100     if (ei_tracelevel >= 4)
101 	ei_show_sendmsg(stderr,header,msg);
102 
103 #ifdef EI_HAVE_STRUCT_IOVEC__
104     if (ei_socket_callbacks_have_writev__(cbs)) {
105         struct iovec v[2];
106 
107         v[0].iov_base = (char *)header;
108         v[0].iov_len = index;
109         v[1].iov_base = (char *)msg;
110         v[1].iov_len = msglen;
111 
112         len = tot_len = (ssize_t) index+msglen;
113         err = ei_writev_fill_ctx_t__(cbs, ctx, v, 2, &len, tmo);
114         if (!err && len != tot_len)
115             err = EIO;
116         if (err) {
117             EI_CONN_SAVE_ERRNO__(err);
118             return ERL_ERROR;
119         }
120 
121         erl_errno = 0;
122 
123         return 0;
124     }
125 #endif /* EI_HAVE_STRUCT_IOVEC__ */
126 
127     /* no writev() */
128     len = tot_len = (ssize_t) index;
129     err = ei_write_fill_ctx_t__(cbs, ctx, header, &len, tmo);
130     if (!err && len != tot_len)
131         err = EIO;
132     if (err) {
133         EI_CONN_SAVE_ERRNO__(err);
134         return ERL_ERROR;
135     }
136 
137     len = tot_len = (ssize_t) msglen;
138     err = ei_write_fill_ctx_t__(cbs, ctx, msg, &len, tmo);
139     if (!err && len != tot_len)
140         err = EIO;
141     if (err) {
142         EI_CONN_SAVE_ERRNO__(err);
143         return ERL_ERROR;
144     }
145 
146     erl_errno = 0;
147 
148     return 0;
149 }
150 
151 
ei_send_reg_encoded(int fd,const erlang_pid * from,const char * to,char * msg,int msglen)152 int ei_send_reg_encoded(int fd, const erlang_pid *from, const char *to,
153 			char *msg, int msglen)
154 {
155     return ei_send_reg_encoded_tmo(fd, from, to, msg, msglen, 0);
156 }
157 
158