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