17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate #include <stdio.h>
287c478bd9Sstevel@tonic-gate #include <stdlib.h>
297c478bd9Sstevel@tonic-gate #include <syslog.h>
307c478bd9Sstevel@tonic-gate #include <string.h>
317c478bd9Sstevel@tonic-gate #include <thread.h>
327c478bd9Sstevel@tonic-gate #include <synch.h>
337c478bd9Sstevel@tonic-gate #include <slp-internal.h>
347c478bd9Sstevel@tonic-gate
357c478bd9Sstevel@tonic-gate /* This is used to pass needed params to consumer_thr and slp_call */
367c478bd9Sstevel@tonic-gate struct thr_call_args {
377c478bd9Sstevel@tonic-gate slp_handle_impl_t *hp;
387c478bd9Sstevel@tonic-gate SLPGenericAppCB *cb;
397c478bd9Sstevel@tonic-gate void *cookie;
407c478bd9Sstevel@tonic-gate SLPMsgReplyCB *msg_cb;
417c478bd9Sstevel@tonic-gate slp_target_list_t *targets;
427c478bd9Sstevel@tonic-gate };
437c478bd9Sstevel@tonic-gate
44*48d1bcbbSToomas Soome static void *consumer(void *);
45*48d1bcbbSToomas Soome static void *slp_call(void *);
467c478bd9Sstevel@tonic-gate static SLPError check_message_fit(slp_handle_impl_t *, slp_target_list_t *);
477c478bd9Sstevel@tonic-gate
slp_ua_common(SLPHandle hSLP,const char * scopes,SLPGenericAppCB cb,void * cookie,SLPMsgReplyCB msg_cb)487c478bd9Sstevel@tonic-gate SLPError slp_ua_common(SLPHandle hSLP, const char *scopes,
49*48d1bcbbSToomas Soome SLPGenericAppCB cb, void *cookie, SLPMsgReplyCB msg_cb)
50*48d1bcbbSToomas Soome {
517c478bd9Sstevel@tonic-gate slp_handle_impl_t *hp;
527c478bd9Sstevel@tonic-gate slp_target_list_t *targets;
537c478bd9Sstevel@tonic-gate struct thr_call_args *args;
547c478bd9Sstevel@tonic-gate slp_queue_t *q;
557c478bd9Sstevel@tonic-gate SLPError err;
567c478bd9Sstevel@tonic-gate thread_t tid;
577c478bd9Sstevel@tonic-gate int terr;
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate hp = (slp_handle_impl_t *)hSLP;
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate /* select targets */
627c478bd9Sstevel@tonic-gate if ((err = slp_new_target_list(hp, scopes, &targets)) != SLP_OK)
637c478bd9Sstevel@tonic-gate return (err);
647c478bd9Sstevel@tonic-gate if ((err = check_message_fit(hp, targets)) != SLP_OK) {
657c478bd9Sstevel@tonic-gate slp_destroy_target_list(targets);
667c478bd9Sstevel@tonic-gate return (err);
677c478bd9Sstevel@tonic-gate }
687c478bd9Sstevel@tonic-gate
697c478bd9Sstevel@tonic-gate /* populate the args structure */
707c478bd9Sstevel@tonic-gate args = malloc(sizeof (*args));
717c478bd9Sstevel@tonic-gate if (args == NULL) {
727c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "ua_common", "out of memory");
737c478bd9Sstevel@tonic-gate return (SLP_MEMORY_ALLOC_FAILED);
747c478bd9Sstevel@tonic-gate }
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate args->hp = hp;
777c478bd9Sstevel@tonic-gate args->cb = cb;
787c478bd9Sstevel@tonic-gate args->cookie = cookie;
797c478bd9Sstevel@tonic-gate args->msg_cb = msg_cb;
807c478bd9Sstevel@tonic-gate args->targets = targets;
817c478bd9Sstevel@tonic-gate
827c478bd9Sstevel@tonic-gate /* create the queue that this call will use */
837c478bd9Sstevel@tonic-gate q = slp_new_queue(&err); /* freed in consumer_thr */
847c478bd9Sstevel@tonic-gate if (err != SLP_OK)
857c478bd9Sstevel@tonic-gate goto error;
867c478bd9Sstevel@tonic-gate hp->q = q;
877c478bd9Sstevel@tonic-gate
887c478bd9Sstevel@tonic-gate /* kick off the producer thread */
89*48d1bcbbSToomas Soome if ((terr = thr_create(NULL, 0, slp_call, args, 0, &tid)) != 0) {
907c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "ua_common", "could not start thread: %s",
91*48d1bcbbSToomas Soome strerror(terr));
927c478bd9Sstevel@tonic-gate err = SLP_INTERNAL_SYSTEM_ERROR;
937c478bd9Sstevel@tonic-gate goto error;
947c478bd9Sstevel@tonic-gate }
957c478bd9Sstevel@tonic-gate hp->producer_tid = tid;
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate if (hp->async) {
987c478bd9Sstevel@tonic-gate /* kick off the consumer thread */
99*48d1bcbbSToomas Soome if ((terr = thr_create(NULL, 0, consumer,
100*48d1bcbbSToomas Soome args, 0, NULL)) != 0) {
1017c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "ua_common",
102*48d1bcbbSToomas Soome "could not start thread: %s",
103*48d1bcbbSToomas Soome strerror(terr));
1047c478bd9Sstevel@tonic-gate err = SLP_INTERNAL_SYSTEM_ERROR;
1057c478bd9Sstevel@tonic-gate /* cleanup producer thread, if necessary */
1067c478bd9Sstevel@tonic-gate hp->cancel = 1;
1077c478bd9Sstevel@tonic-gate (void) thr_join(tid, NULL, NULL);
1087c478bd9Sstevel@tonic-gate
1097c478bd9Sstevel@tonic-gate goto error;
1107c478bd9Sstevel@tonic-gate }
1117c478bd9Sstevel@tonic-gate return (SLP_OK);
1127c478bd9Sstevel@tonic-gate }
1137c478bd9Sstevel@tonic-gate /* else sync */
114*48d1bcbbSToomas Soome return ((SLPError)consumer(args));
1157c478bd9Sstevel@tonic-gate error:
1167c478bd9Sstevel@tonic-gate free(args);
1177c478bd9Sstevel@tonic-gate return (err);
1187c478bd9Sstevel@tonic-gate }
1197c478bd9Sstevel@tonic-gate
120*48d1bcbbSToomas Soome static void *
consumer(void * ap)121*48d1bcbbSToomas Soome consumer(void *ap)
122*48d1bcbbSToomas Soome {
1237c478bd9Sstevel@tonic-gate slp_handle_impl_t *hp;
1247c478bd9Sstevel@tonic-gate char *reply;
1257c478bd9Sstevel@tonic-gate void *collator;
1267c478bd9Sstevel@tonic-gate int numResults = 0;
1277c478bd9Sstevel@tonic-gate struct thr_call_args *args = (struct thr_call_args *)ap;
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate hp = args->hp;
1307c478bd9Sstevel@tonic-gate collator = NULL;
1317c478bd9Sstevel@tonic-gate hp->consumer_tid = thr_self();
1327c478bd9Sstevel@tonic-gate /* while cb wants more and there is more to get ... */
1337c478bd9Sstevel@tonic-gate for (;;) {
1347c478bd9Sstevel@tonic-gate SLPBoolean cont;
1357c478bd9Sstevel@tonic-gate
1367c478bd9Sstevel@tonic-gate reply = slp_dequeue(hp->q);
1377c478bd9Sstevel@tonic-gate /* reply == NULL if no more available or SLPClosed */
1387c478bd9Sstevel@tonic-gate cont = args->msg_cb(hp, reply, args->cb, args->cookie,
139*48d1bcbbSToomas Soome &collator, &numResults);
1407c478bd9Sstevel@tonic-gate
1417c478bd9Sstevel@tonic-gate if (reply) {
142*48d1bcbbSToomas Soome free(reply);
1437c478bd9Sstevel@tonic-gate } else {
144*48d1bcbbSToomas Soome break;
1457c478bd9Sstevel@tonic-gate }
1467c478bd9Sstevel@tonic-gate
1477c478bd9Sstevel@tonic-gate if (!cont) {
148*48d1bcbbSToomas Soome /* cb doesn't want any more; invoke last call */
149*48d1bcbbSToomas Soome args->msg_cb(hp, NULL, args->cb, args->cookie,
150*48d1bcbbSToomas Soome &collator, &numResults);
151*48d1bcbbSToomas Soome break;
1527c478bd9Sstevel@tonic-gate }
1537c478bd9Sstevel@tonic-gate }
1547c478bd9Sstevel@tonic-gate /* cleanup */
1557c478bd9Sstevel@tonic-gate /* clean stop producer [thread] */
1567c478bd9Sstevel@tonic-gate hp->cancel = 1;
1577c478bd9Sstevel@tonic-gate (void) thr_join(hp->producer_tid, NULL, NULL);
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate /* empty and free queue */
1607c478bd9Sstevel@tonic-gate slp_flush_queue(hp->q, free);
1617c478bd9Sstevel@tonic-gate slp_destroy_queue(hp->q);
1627c478bd9Sstevel@tonic-gate
1637c478bd9Sstevel@tonic-gate free(args);
1647c478bd9Sstevel@tonic-gate slp_end_call(hp);
165*48d1bcbbSToomas Soome return ((void *)SLP_OK);
1667c478bd9Sstevel@tonic-gate }
1677c478bd9Sstevel@tonic-gate
1687c478bd9Sstevel@tonic-gate /*
1697c478bd9Sstevel@tonic-gate * This is the producer thread
1707c478bd9Sstevel@tonic-gate */
171*48d1bcbbSToomas Soome static void *
slp_call(void * ap)172*48d1bcbbSToomas Soome slp_call(void *ap)
173*48d1bcbbSToomas Soome {
1747c478bd9Sstevel@tonic-gate struct thr_call_args *args = (struct thr_call_args *)ap;
1757c478bd9Sstevel@tonic-gate slp_target_t *t;
1767c478bd9Sstevel@tonic-gate const char *uc_scopes, *mc_scopes;
1777c478bd9Sstevel@tonic-gate SLPBoolean use_tcp = SLP_FALSE;
1787c478bd9Sstevel@tonic-gate size_t len;
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate /* Unicast */
1817c478bd9Sstevel@tonic-gate if (uc_scopes = slp_get_uc_scopes(args->targets)) {
1827c478bd9Sstevel@tonic-gate size_t mtu;
1837c478bd9Sstevel@tonic-gate int i;
1847c478bd9Sstevel@tonic-gate
1857c478bd9Sstevel@tonic-gate /* calculate msg length */
1867c478bd9Sstevel@tonic-gate len = slp_hdrlang_length(args->hp);
1877c478bd9Sstevel@tonic-gate for (i = 0; i < args->hp->msg.iovlen; i++) {
1887c478bd9Sstevel@tonic-gate len += args->hp->msg.iov[i].iov_len;
1897c478bd9Sstevel@tonic-gate }
1907c478bd9Sstevel@tonic-gate len += strlen(uc_scopes);
1917c478bd9Sstevel@tonic-gate
1927c478bd9Sstevel@tonic-gate mtu = slp_get_mtu();
1937c478bd9Sstevel@tonic-gate if (len > mtu)
1947c478bd9Sstevel@tonic-gate use_tcp = SLP_TRUE;
1957c478bd9Sstevel@tonic-gate
196*48d1bcbbSToomas Soome for (t = slp_next_uc_target(args->targets); t != NULL;
197*48d1bcbbSToomas Soome t = slp_next_uc_target(args->targets)) {
1987c478bd9Sstevel@tonic-gate if (args->hp->cancel)
1997c478bd9Sstevel@tonic-gate break;
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate if (use_tcp)
2027c478bd9Sstevel@tonic-gate slp_uc_tcp_send(args->hp, t, uc_scopes,
203*48d1bcbbSToomas Soome SLP_FALSE, 0);
2047c478bd9Sstevel@tonic-gate else
2057c478bd9Sstevel@tonic-gate slp_uc_udp_send(args->hp, t, uc_scopes);
2067c478bd9Sstevel@tonic-gate }
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate /* Multicast */
2107c478bd9Sstevel@tonic-gate if ((!args->hp->cancel) &&
2117c478bd9Sstevel@tonic-gate (mc_scopes = slp_get_mc_scopes(args->targets)))
2127c478bd9Sstevel@tonic-gate slp_mc_send(args->hp, mc_scopes);
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate /* Wait for TCP to complete, if necessary */
2157c478bd9Sstevel@tonic-gate if (args->hp->tcp_lock)
2167c478bd9Sstevel@tonic-gate slp_tcp_wait(args->hp);
2177c478bd9Sstevel@tonic-gate
2187c478bd9Sstevel@tonic-gate slp_destroy_target_list(args->targets);
2197c478bd9Sstevel@tonic-gate
2207c478bd9Sstevel@tonic-gate /* free the message */
2217c478bd9Sstevel@tonic-gate free(args->hp->msg.iov);
2227c478bd9Sstevel@tonic-gate free(args->hp->msg.msg);
2237c478bd9Sstevel@tonic-gate
2247c478bd9Sstevel@tonic-gate /* null terminate message queue */
2257c478bd9Sstevel@tonic-gate (void) slp_enqueue(args->hp->q, NULL);
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate thr_exit(NULL); /* we're outa here */
2287c478bd9Sstevel@tonic-gate }
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate /*
2317c478bd9Sstevel@tonic-gate * If the message to be sent needs to be multicast, check that it
2327c478bd9Sstevel@tonic-gate * can fit into a datagram. If not, return BUFFER_OVERFLOW, otherwise
2337c478bd9Sstevel@tonic-gate * return SLP_OK.
2347c478bd9Sstevel@tonic-gate */
check_message_fit(slp_handle_impl_t * hp,slp_target_list_t * targets)2357c478bd9Sstevel@tonic-gate static SLPError check_message_fit(slp_handle_impl_t *hp,
2367c478bd9Sstevel@tonic-gate slp_target_list_t *targets) {
2377c478bd9Sstevel@tonic-gate size_t msgSize;
2387c478bd9Sstevel@tonic-gate int i;
2397c478bd9Sstevel@tonic-gate const char *mc_scopes;
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate if (!(mc_scopes = slp_get_mc_scopes(targets)))
2427c478bd9Sstevel@tonic-gate return (SLP_OK); /* no mc targets to worry about */
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate msgSize = slp_hdrlang_length(hp);
2457c478bd9Sstevel@tonic-gate for (i = 0; i < hp->msg.iovlen; i++) {
2467c478bd9Sstevel@tonic-gate msgSize += hp->msg.iov[i].iov_len;
2477c478bd9Sstevel@tonic-gate }
2487c478bd9Sstevel@tonic-gate msgSize += strlen(mc_scopes);
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate if (msgSize > slp_get_mtu())
2517c478bd9Sstevel@tonic-gate return (SLP_BUFFER_OVERFLOW);
2527c478bd9Sstevel@tonic-gate return (SLP_OK);
2537c478bd9Sstevel@tonic-gate }
254