2 * Copyright (c) 2001-2003
3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
6 * Author: Harti Brandt <harti@freebsd.org>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * $Begemot: libunimsg/sscop/sscop_main.c,v 1.5 2005/05/23 11:46:17 brandt_h Exp $
32 #include <sys/types.h>
33 #include <sys/socket.h>
45 #include <netnatm/unimsg.h>
46 #include <netnatm/saal/sscop.h>
49 static int sigusr1; /* got SIGUSR1 */
50 static int unidir; /* write only user */
51 static int end_at_eof = 1; /* send RELEASE_request at user EOF */
53 static volatile int ready; /* flag if connection is established */
54 static volatile int finished; /* got release confirm or indication */
56 static const char usgtxt[] = "\
57 SSCOP transport protocol\n\
58 Usage: sscop [-h] [-Fbefirwx3] [-ap=v] [-lN] [-tt=m] [-v X] [-V X] [-W N]\n\
60 -F use framing for sscop also\n\
61 -V X set verbose flags to hex X\n\
62 -W N set initial window to N\n\
63 -a p=v set parameter 'p' to 'v'\n\
64 -b enable robustness enhancement\n\
65 -e don't RELEASE_request on user EOF\n\
66 -f use begemot frame functions for user fd\n\
68 -i use user fd only for output\n\
69 -lN loose every nth message\n\
70 -r reverse user and sscop file descriptors\n\
71 -t t=m set timer 't' to 'm' milliseconds\n\
72 -v X set sscop verbose flags to hex X\n\
73 -w don't start conversation\n\
74 -x enable POLL after retransmission\n\
75 -3 redirect output to fd 3\n\
76 Timers are cc, poll, ka, nr or idle; parameters are j, k, cc, pd or stat.\n";
78 static void sscop_send_manage(struct sscop *, void *,
79 enum sscop_maasig, struct uni_msg *, u_int, u_int);
80 static void sscop_send_upper(struct sscop *, void *, enum sscop_aasig,
81 struct SSCOP_MBUF_T *, u_int);
82 static void sscop_send_lower(struct sscop *, void *, struct SSCOP_MBUF_T *);
84 static const struct sscop_funcs sscop_funcs = {
94 * SSCOP file descriptor is ready. Allocate and read one message
95 * and dispatch a signal.
99 proto_infunc(int fd, int mask __unused, void *uap)
102 proto_infunc(evContext ctx __unused, void *uap, int fd, int mask __unused)
107 if ((m = proto_msgin(fd)) != NULL)
108 sscop_input((struct sscop *)uap, m);
112 * User input. Allocate and read message and dispatch signal.
114 #ifdef USE_LIBBEGEMOT
116 user_infunc(int fd, int mask __unused, void *uap)
119 user_infunc(evContext ctx __unused, void *uap, int fd, int mask __unused)
124 if ((m = user_msgin(fd)) != NULL)
125 sscop_aasig((struct sscop *)uap, SSCOP_DATA_request, m, 0);
128 sscop_aasig((struct sscop *)uap, SSCOP_RELEASE_request, 0, 0);
132 onusr1(int s __unused)
138 main(int argc, char *argv[])
142 struct sscop_param param;
146 #ifndef USE_LIBBEGEMOT
151 * Default is to have the USER on stdin and SSCOP on stdout
157 memset(¶m, 0, sizeof(param));
158 param.maxk = MAXUSRMSG;
161 mask = SSCOP_SET_MAXK | SSCOP_SET_MAXJ | SSCOP_SET_MAXCC;
163 while((opt = getopt(argc, argv, "3a:befFhil:rt:v:V:wW:x")) != -1)
183 fprintf(stderr, usgtxt);
191 loose = strtoul(optarg, NULL, 0);
200 sscop_vflag = strtoul(optarg, NULL, 16);
204 verbose = strtoul(optarg, NULL, 16);
216 parse_param(¶m, &mask, opt, optarg);
221 user_out_fd = user_fd;
223 #ifndef USE_LIBBEGEMOT
224 if (evCreate(&evctx))
231 sa.sa_handler = onusr1;
232 sigemptyset(&sa.sa_mask);
233 sa.sa_flags = SA_RESTART;
234 if(sigaction(SIGUSR1, &sa, NULL))
235 err(1, "sigaction(SIGUSR1)");
238 * Allocate and initialize SSCOP
240 if ((sscop = sscop_create(NULL, &sscop_funcs)) == NULL)
242 sscop_setdebug(sscop, sscop_vflag);
243 if ((errno = sscop_setparam(sscop, ¶m, &mask)) != 0)
244 err(1, "can't set sscop parameters %#x", mask);
249 #ifdef USE_LIBBEGEMOT
250 if ((sscop_h = poll_register(sscop_fd, proto_infunc,
251 sscop, POLL_IN)) == -1)
252 err(1, "can't select on sscop fd");
254 if (evSelectFD(evctx, sscop_fd, EV_READ, proto_infunc, sscop, &sscop_h))
255 err(1, "can't select on sscop fd");
259 * if we are active - send establish request
262 sscop_aasig(sscop, SSCOP_ESTABLISH_request, NULL, 1);
265 * Run protocol until it get's ready
267 while (sscop_fd >= 0 && !ready) {
268 #ifdef USE_LIBBEGEMOT
271 if (evGetNext(evctx, &ev, EV_WAIT) == 0) {
272 if (evDispatch(evctx, ev))
273 err(1, "dispatch event");
274 } else if (errno != EINTR)
280 * If this led to a closed file - exit.
283 VERBOSE(("SSCOP file descriptor closed - exiting"));
284 sscop_destroy(sscop);
288 VERBOSE(("READY - starting data transfer"));
291 #ifdef USE_LIBBEGEMOT
292 ((user_h = poll_register(user_fd, user_infunc, sscop, POLL_IN)) == -1))
294 evSelectFD(evctx, user_fd, EV_READ, user_infunc, sscop, &user_h))
296 err(1, "can't select on sscop fd");
298 while (!sigusr1 && sscop_fd >= 0) {
299 #ifdef USE_LIBBEGEMOT
302 if (evGetNext(evctx, &ev, EV_WAIT) == 0) {
303 if (evDispatch(evctx, ev))
304 err(1, "dispatch event");
305 } else if (errno != EINTR)
310 if (sigusr1 && sscop_fd >= 0) {
312 * Release if we still have the connection
314 sscop_aasig(sscop, SSCOP_RELEASE_request, NULL, 0);
315 while (!finished && sscop_fd >= 0) {
316 #ifdef USE_LIBBEGEMOT
319 if (evGetNext(evctx, &ev, EV_WAIT) == 0) {
320 if (evDispatch(evctx, ev))
321 err(1, "dispatch event");
322 } else if (errno != EINTR)
328 VERBOSE(("SSCOP file descriptor closed - exiting"));
329 sscop_destroy(sscop);
340 sscop_send_lower(struct sscop *sscop __unused, void *arg __unused,
341 struct SSCOP_MBUF_T *m)
348 * Write the message to the user and move the window
351 uoutput(struct sscop *sscop, struct uni_msg *m)
354 sscop_window(sscop, +1);
361 sscop_send_upper(struct sscop *sscop, void *arg __unused, enum sscop_aasig sig,
362 struct SSCOP_MBUF_T *m, u_int p __unused)
364 VERBOSE(("--> got aa %d(%s)", sig, sscop_signame(sig)));
368 case SSCOP_RELEASE_indication:
370 VERBOSE((" ... exiting"));
371 #ifdef USE_LIBBEGEMOT
372 poll_unregister(sscop_h);
374 evDeselectFD(evctx, sscop_h);
376 (void)close(sscop_fd);
384 case SSCOP_RELEASE_confirm:
386 VERBOSE((" ... exiting"));
387 #ifdef USE_LIBBEGEMOT
388 poll_unregister(sscop_h);
390 evDeselectFD(evctx, sscop_h);
392 (void)close(sscop_fd);
398 case SSCOP_ESTABLISH_indication:
399 sscop_aasig(sscop, SSCOP_ESTABLISH_response, NULL, 1);
405 case SSCOP_ESTABLISH_confirm:
411 case SSCOP_DATA_indication:
416 case SSCOP_UDATA_indication:
418 VERBOSE(("UDATA.indication ignored"));
422 case SSCOP_RECOVER_indication:
423 sscop_aasig(sscop, SSCOP_RECOVER_response, NULL, 0);
426 case SSCOP_RESYNC_indication:
427 sscop_aasig(sscop, SSCOP_RESYNC_response, NULL, 0);
432 case SSCOP_RESYNC_confirm:
435 case SSCOP_RETRIEVE_indication:
436 case SSCOP_RETRIEVE_COMPL_indication:
437 warnx("Ooops. A retrieve indication");
440 case SSCOP_ESTABLISH_request:
441 case SSCOP_RELEASE_request:
442 case SSCOP_ESTABLISH_response:
443 case SSCOP_DATA_request:
444 case SSCOP_UDATA_request:
445 case SSCOP_RECOVER_response:
446 case SSCOP_RESYNC_request:
447 case SSCOP_RESYNC_response:
448 case SSCOP_RETRIEVE_request:
449 warnx("bad signal for this direction");
455 * This get's called for MAAL
458 sscop_send_manage(struct sscop *sscop __unused, void *arg __unused,
459 enum sscop_maasig sig, struct uni_msg *m, u_int error, u_int cnt)
461 VERBOSE(("--> got maa %d(%s)", sig, sscop_msigname(sig)));
465 case SSCOP_MDATA_indication:
466 VERBOSE(("MDATA.indication ignored"));
470 case SSCOP_MERROR_indication:
471 VERBOSE(("MAAL-ERROR.indication '%c' %u", error, cnt));
474 case SSCOP_MDATA_request:
475 warnx("bad signal for this direction");