4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
35 #include <slp-internal.h>
37 /* This is used to pass needed params to consumer_thr and slp_call */
38 struct thr_call_args
{
39 slp_handle_impl_t
*hp
;
42 SLPMsgReplyCB
*msg_cb
;
43 slp_target_list_t
*targets
;
46 static SLPError
consumer(void *);
47 static void slp_call(void *);
48 static SLPError
check_message_fit(slp_handle_impl_t
*, slp_target_list_t
*);
50 SLPError
slp_ua_common(SLPHandle hSLP
, const char *scopes
,
51 SLPGenericAppCB cb
, void *cookie
,
52 SLPMsgReplyCB msg_cb
) {
53 slp_handle_impl_t
*hp
;
54 slp_target_list_t
*targets
;
55 struct thr_call_args
*args
;
61 hp
= (slp_handle_impl_t
*)hSLP
;
64 if ((err
= slp_new_target_list(hp
, scopes
, &targets
)) != SLP_OK
)
66 if ((err
= check_message_fit(hp
, targets
)) != SLP_OK
) {
67 slp_destroy_target_list(targets
);
71 /* populate the args structure */
72 args
= malloc(sizeof (*args
));
74 slp_err(LOG_CRIT
, 0, "ua_common", "out of memory");
75 return (SLP_MEMORY_ALLOC_FAILED
);
80 args
->cookie
= cookie
;
81 args
->msg_cb
= msg_cb
;
82 args
->targets
= targets
;
84 /* create the queue that this call will use */
85 q
= slp_new_queue(&err
); /* freed in consumer_thr */
90 /* kick off the producer thread */
91 if ((terr
= thr_create(
92 NULL
, 0, (void *(*)(void *)) slp_call
, args
, 0, &tid
)) != 0) {
93 slp_err(LOG_CRIT
, 0, "ua_common", "could not start thread: %s",
95 err
= SLP_INTERNAL_SYSTEM_ERROR
;
98 hp
->producer_tid
= tid
;
101 /* kick off the consumer thread */
102 if ((terr
= thr_create(
103 NULL
, 0, (void *(*)(void *))consumer
,
104 args
, 0, NULL
)) != 0) {
105 slp_err(LOG_CRIT
, 0, "ua_common",
106 "could not start thread: %s",
108 err
= SLP_INTERNAL_SYSTEM_ERROR
;
109 /* cleanup producer thread, if necessary */
111 (void) thr_join(tid
, NULL
, NULL
);
118 return (consumer(args
));
124 static SLPError
consumer(void *ap
) {
125 slp_handle_impl_t
*hp
;
129 struct thr_call_args
*args
= (struct thr_call_args
*)ap
;
133 hp
->consumer_tid
= thr_self();
134 /* while cb wants more and there is more to get ... */
138 reply
= slp_dequeue(hp
->q
);
139 /* reply == NULL if no more available or SLPClosed */
140 cont
= args
->msg_cb(hp
, reply
, args
->cb
, args
->cookie
,
141 &collator
, &numResults
);
150 /* cb doesn't want any more; invoke last call */
151 args
->msg_cb(hp
, NULL
, args
->cb
, args
->cookie
,
152 &collator
, &numResults
);
157 /* clean stop producer [thread] */
159 (void) thr_join(hp
->producer_tid
, NULL
, NULL
);
161 /* empty and free queue */
162 slp_flush_queue(hp
->q
, free
);
163 slp_destroy_queue(hp
->q
);
171 * This is the producer thread
173 static void slp_call(void *ap
) {
174 struct thr_call_args
*args
= (struct thr_call_args
*)ap
;
176 const char *uc_scopes
, *mc_scopes
;
177 SLPBoolean use_tcp
= SLP_FALSE
;
181 if (uc_scopes
= slp_get_uc_scopes(args
->targets
)) {
185 /* calculate msg length */
186 len
= slp_hdrlang_length(args
->hp
);
187 for (i
= 0; i
< args
->hp
->msg
.iovlen
; i
++) {
188 len
+= args
->hp
->msg
.iov
[i
].iov_len
;
190 len
+= strlen(uc_scopes
);
197 t
= slp_next_uc_target(args
->targets
);
199 t
= slp_next_uc_target(args
->targets
)) {
200 if (args
->hp
->cancel
)
204 slp_uc_tcp_send(args
->hp
, t
, uc_scopes
,
207 slp_uc_udp_send(args
->hp
, t
, uc_scopes
);
212 if ((!args
->hp
->cancel
) &&
213 (mc_scopes
= slp_get_mc_scopes(args
->targets
)))
214 slp_mc_send(args
->hp
, mc_scopes
);
216 /* Wait for TCP to complete, if necessary */
217 if (args
->hp
->tcp_lock
)
218 slp_tcp_wait(args
->hp
);
220 slp_destroy_target_list(args
->targets
);
222 /* free the message */
223 free(args
->hp
->msg
.iov
);
224 free(args
->hp
->msg
.msg
);
226 /* null terminate message queue */
227 (void) slp_enqueue(args
->hp
->q
, NULL
);
229 thr_exit(NULL
); /* we're outa here */
233 * If the message to be sent needs to be multicast, check that it
234 * can fit into a datagram. If not, return BUFFER_OVERFLOW, otherwise
237 static SLPError
check_message_fit(slp_handle_impl_t
*hp
,
238 slp_target_list_t
*targets
) {
241 const char *mc_scopes
;
243 if (!(mc_scopes
= slp_get_mc_scopes(targets
)))
244 return (SLP_OK
); /* no mc targets to worry about */
246 msgSize
= slp_hdrlang_length(hp
);
247 for (i
= 0; i
< hp
->msg
.iovlen
; i
++) {
248 msgSize
+= hp
->msg
.iov
[i
].iov_len
;
250 msgSize
+= strlen(mc_scopes
);
252 if (msgSize
> slp_get_mtu())
253 return (SLP_BUFFER_OVERFLOW
);