xref: /trueos/usr.bin/mach-tests/ipc-hello/ipc-hello.c (revision 4c26ab344835e45587dd7ff3e3af149b4a89959f)
1 /*
2    Copyright (C) 2002 Neal H. Walfield  <neal@cs.uml.edu>
3 
4    This is free software; you can redistribute it and/or modify it
5    under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8 
9    This program has been distributed in the hope that it will be
10    useful, but WITHOUT ANY WARRANTY; without even the implied warranty
11    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111,
17    USA. */
18 #include <sys/cdefs.h>
19 #include <sys/types.h>
20 
21 #include <assert.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <pthread.h>
26 #include <mach/mach.h>
27 
28 
29 static void
error(int exitcode,int macherr,const char * funcname)30 error(int exitcode, int macherr, const char *funcname)
31 {
32 #if 0
33 	mach_error(funcname, macherr);
34 #endif
35 	printf("%s failed with %x\n", funcname, macherr);
36 	exit(1);
37 }
38 
39 #define MACH_MSG_TYPE_STRING 12
40 #define MSG_DEBUGGING 0
41 
42 typedef void *any_t;
43 
44 typedef struct {
45 	boolean_t msgt_deallocate;
46 	boolean_t msgt_longform;
47 	boolean_t msgt_inline;
48 	uint32_t msgt_number;
49 	uint32_t msgt_unused;
50 	uint32_t msgt_name;
51 	size_t msgt_size;
52 } mach_msg_type_t;
53 
54 struct message
55 {
56 	mach_msg_header_t header;
57 	mach_msg_type_t type;
58 	char data[256];
59 };
60 
61 struct message_recv
62 {
63 	mach_msg_header_t header;
64 	mach_msg_type_t type;
65 	char data[256];
66 	mach_msg_trailer_t trailer;
67 };
68 
69 #if MSG_DEBUGGING
70 static void
print_msg_type(mach_msg_type_t * type)71 print_msg_type(mach_msg_type_t *type)
72 {
73 	printf("msgt_deallocate=%c\n", type->msgt_deallocate ? 'T' : 'F');
74 	printf("msgt_longform=%c\n", type->msgt_deallocate ? 'T' : 'F');
75 	printf("msgt_inline=%c\n", type->msgt_deallocate ? 'T' : 'F');
76 	printf("msgt_number=%u\n", type->msgt_number);
77 	printf("msgt_unused=%u\n", type->msgt_unused);
78 	printf("msgt_name=%u\n", type->msgt_name);
79 	printf("msgt_size=%lu\n", type->msgt_size);
80 }
81 
82 static void
print_msg_header(mach_msg_header_t * hdr)83 print_msg_header(mach_msg_header_t *hdr)
84 {
85 	printf("msgh_bits=%08x\n", hdr->msgh_bits);
86 	printf("msgh_size=%d\n", hdr->msgh_size);
87 	printf("msgh_remote_port=%d\n", hdr->msgh_remote_port);
88 	printf("msgh_local_port=%d\n", hdr->msgh_local_port);
89 	printf("msgh_voucher_port=%d\n", hdr->msgh_voucher_port);
90 	printf("msgh_id=%d\n", hdr->msgh_id);
91 }
92 #else
print_msg_type(mach_msg_type_t * type __unused)93 static void print_msg_type(mach_msg_type_t *type __unused) {}
print_msg_header(mach_msg_header_t * hdr __unused)94 static void print_msg_header(mach_msg_header_t *hdr __unused) {}
95 #endif
96 
97 any_t
server(any_t arg)98 server (any_t arg)
99 {
100 	mach_port_t port = *(mach_port_t *) arg;
101 	int err;
102 	struct message message1 = { 0 };
103 	struct message_recv message = { 0 };
104 
105 	message.header.msgh_local_port = port;
106 	message.header.msgh_size = sizeof (message);
107 	while (1)
108 	{
109 		/* Receive a message.  */
110 #if MSG_DEBUGGING
111 		fprintf(stderr, "About to call mach_msg - receiving at msg=%p\n", &message.header);
112 #endif
113 		err = mach_msg (&message.header,		/* The header */
114 				MACH_RCV_MSG,		/* Flags */
115 				0,			/* Send size */
116 				sizeof (message),	/* Max receive size */
117 				port,			/* Receive port */
118 				MACH_MSG_TIMEOUT_NONE,	/* No timeout */
119 				MACH_PORT_NULL);		/* No notification */
120 		if (err)
121 			error (1, err, "server mach_msg MACH_RCV_MSG");
122 #if MSG_DEBUGGING
123 		printf("received:\n");
124 		print_msg_header(&message.header);
125 		print_msg_type(&message.type);
126 		printf("data: %s\n", message.data);
127 #endif
128 		/* Verify the type tag */
129 		assert (message.type.msgt_name == MACH_MSG_TYPE_STRING);
130 
131 		/* Copy the contents so that we can create a reply string.  */
132 		{
133 			char *temp = strndup(message.data, 250);
134 #if MSG_DEBUGGING
135 			printf("server received: %s\n", temp);
136 #endif
137 			sprintf (message.data, "Hello %s", temp);
138 			printf("server sending: %s\n", message.data);
139 			free (temp);
140 		}
141 
142 		/* Fix the header.  */
143 		message.header.msgh_local_port = MACH_PORT_NULL;
144 
145 		/* Fix the type header.  */
146 		message.type.msgt_size = strlen(message.data) * 8;
147 
148 		/* Send the reply.  */
149 		err = mach_msg (&message.header,		/* The message header */
150 				MACH_SEND_MSG,		/* Flags */
151 				sizeof (message),	/* Send size */
152 				0,			/* Max receive size */
153 				MACH_PORT_NULL,		/* Receive port */
154 				MACH_MSG_TIMEOUT_NONE,	/* No timeout */
155 				MACH_PORT_NULL);		/* No notification */
156 		if (err)
157 			error (2, err, "server mach_msg send");
158 	}
159 
160 	return 0;
161 }
162 
163 #define DO_INSERT_RIGHT 1
164 int
main(int argc,char * argv[])165 main (int argc, char *argv[])
166 {
167 	mach_port_t port;
168 	mach_port_t receive;
169 	pthread_t ptd;
170 	int err;
171 
172 	/* Allocate a port.  */
173 	err = mach_port_allocate (mach_task_self (),
174 				  MACH_PORT_RIGHT_RECEIVE, &port);
175 	if (err)
176 		error (1, err, "mach_port_allocate");
177 
178 #if DO_INSERT_RIGHT
179 	err = mach_port_insert_right (mach_task_self (),
180 				      port,
181 				      port,
182 				      MACH_MSG_TYPE_MAKE_SEND);
183 
184 	if (err)
185 		error(10, err, "mach_port_insert_right");
186 #endif
187 
188 	err = mach_port_allocate (mach_task_self (),
189 				  MACH_PORT_RIGHT_RECEIVE, &receive);
190 	if (err)
191 		error (1, err, "mach_port_allocate");
192 
193 #if DO_INSERT_RIGHT
194 	err = mach_port_insert_right (mach_task_self (),
195 				      receive,
196 				      receive,
197 				      MACH_MSG_TYPE_MAKE_SEND);
198 	if (err)
199 		error(10, err, "mach_port_insert_right receive");
200 #endif
201 
202 	printf("sizeof(message)=%ld sizeof(message_recv)=%ld\n",
203 		   sizeof(struct message), sizeof(struct message_recv));
204 	/* Create a new thread to wait for the message */
205 	if (pthread_create(&ptd, NULL, server, &port)) {
206 		perror("pthread_create failed");
207 		exit(1);
208 	}
209 
210 
211 	/* Send a message down the port */
212 	while (1)
213 	{
214 		struct message message;
215 
216 		printf ("Enter your name: ");
217 		fgets (message.data, sizeof (message.data) - 8, stdin);
218 
219 		if (feof (stdin))
220 			break;
221 
222 #if 0
223 		message.header.msgh_bits
224 			= MACH_MSGH_BITS (MACH_MSG_TYPE_MAKE_SEND,
225 					  MACH_MSG_TYPE_MAKE_SEND_ONCE);
226 #else
227 		message.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND);
228 #endif
229 
230 		message.header.msgh_remote_port = port;		/* Request port */
231 		message.header.msgh_local_port = receive;		/* Reply port */
232 		message.header.msgh_id = 0;			/* Message id */
233 		message.header.msgh_size = sizeof (message);	/* Message size */
234 
235 		message.type.msgt_name = MACH_MSG_TYPE_STRING;	/* Parameter type */
236 		message.type.msgt_size = 8 * (strlen (message.data) + 1); /* # Bits */
237 		message.type.msgt_number = 1;			/* Number of elements */
238 		message.type.msgt_inline = TRUE;			/* Inlined */
239 		message.type.msgt_longform = FALSE;		/* Shortform */
240 		message.type.msgt_deallocate = FALSE;		/* Do not deallocate */
241 		message.type.msgt_unused = 0;			/* = 0 */
242 		printf("sending:\n");
243 		print_msg_header(&message.header);
244 		print_msg_type(&message.type);
245 		printf("data: %s\n", message.data);
246 
247 		/* Send the message on its way and wait for a reply.  */
248 		err = mach_msg (&message.header,			/* The header */
249 				MACH_SEND_MSG /*| MACH_RCV_MSG*/ ,	/* Flags */
250 				sizeof (message),			/* Send size */
251 				0, //sizeof (message),			/* Max receive Size */
252 				receive,				/* Receive port */
253 				MACH_MSG_TIMEOUT_NONE,		/* No timeout */
254 				MACH_PORT_NULL);			/* No notification */
255 		if (err)
256 			error (3, err, "client mach_msg");
257 		else
258 			fprintf(stderr, "Sent a message\n");
259 		/* Verify the type tag */
260 		assert (message.type.msgt_name == MACH_MSG_TYPE_STRING);
261 
262 		printf ("Server said: %s", message.data);
263 	}
264 
265 	return 0;
266 }
267