1121330Sharti/*
2121330Sharti * Copyright (c) 2001-2003
3121330Sharti *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4121330Sharti * 	All rights reserved.
5121330Sharti *
6121330Sharti * Redistribution and use in source and binary forms, with or without
7121330Sharti * modification, are permitted provided that the following conditions
8121330Sharti * are met:
9121330Sharti * 1. Redistributions of source code must retain the above copyright
10121330Sharti *    notice, this list of conditions and the following disclaimer.
11121330Sharti * 2. Redistributions in binary form must reproduce the above copyright
12121330Sharti *    notice, this list of conditions and the following disclaimer in the
13121330Sharti *    documentation and/or other materials provided with the distribution.
14121330Sharti *
15121330Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16121330Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17121330Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18121330Sharti * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19121330Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20121330Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21121330Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22121330Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23121330Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24121330Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25121330Sharti * SUCH DAMAGE.
26121330Sharti *
27121330Sharti * Author: Hartmut Brandt <harti@freebsd.org>
28121330Sharti *
29131823Sharti * $Begemot: libunimsg/libngatm/sscopcust.h,v 1.4 2004/07/08 08:21:40 brandt Exp $
30121330Sharti *
31121330Sharti * Customisation of the SSCOP code for the user space library.
32121330Sharti */
33121330Sharti#include <sys/types.h>
34121330Sharti#include <sys/queue.h>
35121330Sharti#include <stdio.h>
36121330Sharti#include <stdlib.h>
37121330Sharti#include <string.h>
38121330Sharti#include <stdarg.h>
39121330Sharti#include <errno.h>
40121330Sharti#ifdef SSCOP_DEBUG
41121330Sharti#include <assert.h>
42121330Sharti#endif
43121330Sharti#include <netinet/in.h>
44121330Sharti#include <arpa/inet.h>
45121330Sharti#include <netnatm/unimsg.h>
46121330Sharti
47121330Sharti/*
48121330Sharti * Allocate zeroed or non-zeroed memory of some size and cast it.
49121330Sharti * Return NULL on failure.
50121330Sharti */
51121330Sharti#define	MEMINIT()
52121330Sharti
53121330Sharti#define	MEMZALLOC(PTR,CAST,SIZE) do {				\
54121330Sharti	void *_m = malloc(SIZE);				\
55121330Sharti	if (_m != NULL)						\
56121330Sharti		bzero(_m, SIZE);				\
57121330Sharti	(PTR) = (CAST)_m;					\
58121330Sharti} while(0)
59121330Sharti
60121330Sharti#define	MEMFREE(PTR) free(PTR);
61121330Sharti
62121330Sharti#define	MSG_ALLOC(PTR) \
63121330Sharti	MEMZALLOC(PTR, struct sscop_msg *, sizeof(struct sscop_msg))
64121330Sharti#define	MSG_FREE(PTR) \
65121330Sharti	MEMFREE(PTR)
66121330Sharti
67121330Sharti#define	SIG_ALLOC(PTR) \
68121330Sharti	MEMZALLOC(PTR, struct sscop_sig *, sizeof(struct sscop_sig))
69121330Sharti#define	SIG_FREE(PTR) \
70121330Sharti	MEMFREE(PTR)
71121330Sharti
72121330Sharti/*
73121330Sharti * Timer support.
74121330Sharti */
75121330Shartitypedef void *sscop_timer_t;
76121330Sharti#define	TIMER_INIT(S,T)	(S)->t_##T = NULL
77121330Sharti#define	TIMER_STOP(S,T) do {						\
78121330Sharti	if ((S)->t_##T != NULL) {					\
79121330Sharti		(S)->funcs->stop_timer((S), (S)->aarg, (S)->t_##T);	\
80121330Sharti		(S)->t_##T = NULL;					\
81121330Sharti	}								\
82121330Sharti    } while(0)
83121330Sharti#define	TIMER_RESTART(S,T) do {						\
84121330Sharti	if ((S)->t_##T != NULL)						\
85121330Sharti		(S)->funcs->stop_timer((S), (S)->aarg, (S)->t_##T);	\
86121330Sharti	(S)->t_##T = (S)->funcs->start_timer((S), (S)->aarg,		\
87121330Sharti	    (S)->timer##T, T##_func);					\
88121330Sharti    } while(0)
89121330Sharti#define	TIMER_ISACT(S,T)	((S)->t_##T != NULL)
90121330Sharti
91121330Sharti#define	TIMER_FUNC(T,N)							\
92121330Shartistatic void								\
93121330ShartiT##_func(void *varg)							\
94121330Sharti{									\
95121330Sharti	struct sscop *sscop = varg;					\
96121330Sharti	VERBOSE(sscop, SSCOP_DBG_TIMER, (sscop, sscop->aarg,		\
97121330Sharti	    "timer_" #T " expired"));					\
98121330Sharti	sscop->t_##T = NULL;						\
99121330Sharti	sscop_signal(sscop, SIG_T_##N, NULL);				\
100121330Sharti}
101121330Sharti
102121330Sharti
103121330Sharti/*
104121330Sharti * Message queues
105121330Sharti */
106121330Shartitypedef TAILQ_ENTRY(sscop_msg) sscop_msgq_link_t;
107121330Shartitypedef TAILQ_HEAD(sscop_msgq, sscop_msg) sscop_msgq_head_t;
108121330Sharti#define	MSGQ_EMPTY(Q) TAILQ_EMPTY(Q)
109121330Sharti#define	MSGQ_INIT(Q) TAILQ_INIT(Q)
110121330Sharti#define	MSGQ_FOREACH(P,Q) TAILQ_FOREACH(P,Q,link)
111121330Sharti#define	MSGQ_REMOVE(Q,M) TAILQ_REMOVE(Q,M,link)
112121330Sharti#define	MSGQ_INSERT_BEFORE(B,M) TAILQ_INSERT_BEFORE(B,M,link)
113121330Sharti#define	MSGQ_APPEND(Q,M) TAILQ_INSERT_TAIL(Q,M,link)
114121330Sharti#define	MSGQ_PEEK(Q) (TAILQ_EMPTY((Q)) ? NULL : TAILQ_FIRST((Q)))
115121330Sharti#define	MSGQ_GET(Q)							\
116121330Sharti    ({									\
117121330Sharti	struct sscop_msg *_m = NULL;					\
118121330Sharti									\
119121330Sharti	if(!TAILQ_EMPTY(Q)) {						\
120121330Sharti		_m = TAILQ_FIRST(Q);					\
121121330Sharti		TAILQ_REMOVE(Q, _m, link);				\
122121330Sharti	}								\
123121330Sharti	_m;								\
124121330Sharti    })
125121330Sharti
126121330Sharti#define	MSGQ_CLEAR(Q)							\
127121330Sharti	do {								\
128121330Sharti		struct sscop_msg *_m1, *_m2;				\
129121330Sharti									\
130121330Sharti		_m1 = TAILQ_FIRST(Q);					\
131121330Sharti		while(_m1 != NULL) {					\
132121330Sharti			_m2 = TAILQ_NEXT(_m1, link);			\
133121330Sharti			SSCOP_MSG_FREE(_m1);				\
134121330Sharti			_m1 = _m2;					\
135121330Sharti		}							\
136121330Sharti		TAILQ_INIT((Q));					\
137121330Sharti	} while(0)
138121330Sharti
139121330Sharti/*
140121330Sharti * Signal queues
141121330Sharti */
142121330Shartitypedef TAILQ_ENTRY(sscop_sig) sscop_sigq_link_t;
143121330Shartitypedef TAILQ_HEAD(sscop_sigq, sscop_sig) sscop_sigq_head_t;
144121330Sharti#define	SIGQ_INIT(Q) 		TAILQ_INIT(Q)
145121330Sharti#define	SIGQ_APPEND(Q,S)	TAILQ_INSERT_TAIL(Q, S, link)
146121330Sharti#define	SIGQ_EMPTY(Q)		TAILQ_EMPTY(Q)
147121330Sharti#define	SIGQ_GET(Q)							\
148121330Sharti    ({									\
149121330Sharti	struct sscop_sig *_s = NULL;					\
150121330Sharti									\
151121330Sharti	if(!TAILQ_EMPTY(Q)) {						\
152121330Sharti		_s = TAILQ_FIRST(Q);					\
153121330Sharti		TAILQ_REMOVE(Q, _s, link);				\
154121330Sharti	}								\
155121330Sharti	_s;								\
156121330Sharti    })
157121330Sharti
158121330Sharti#define	SIGQ_MOVE(F,T)							\
159121330Sharti    do {								\
160121330Sharti	struct sscop_sig *_s;						\
161121330Sharti									\
162121330Sharti	while(!TAILQ_EMPTY(F)) {					\
163121330Sharti		_s = TAILQ_FIRST(F);					\
164121330Sharti		TAILQ_REMOVE(F, _s, link);				\
165121330Sharti		TAILQ_INSERT_TAIL(T, _s, link);				\
166121330Sharti	}								\
167121330Sharti    } while(0)
168121330Sharti
169121330Sharti#define	SIGQ_PREPEND(F,T)						\
170121330Sharti    do {								\
171121330Sharti	struct sscop_sig *_s;						\
172121330Sharti									\
173121330Sharti	while(!TAILQ_EMPTY(F)) {					\
174121330Sharti		_s = TAILQ_LAST(F, sscop_sigq);				\
175121330Sharti		TAILQ_REMOVE(F, _s, link);				\
176121330Sharti		TAILQ_INSERT_HEAD(T, _s, link);				\
177121330Sharti	}								\
178121330Sharti    } while(0)
179121330Sharti
180121330Sharti#define	SIGQ_CLEAR(Q)							\
181121330Sharti    do {								\
182121330Sharti	struct sscop_sig *_s1, *_s2;					\
183121330Sharti									\
184121330Sharti	_s1 = TAILQ_FIRST(Q);						\
185121330Sharti	while(_s1 != NULL) {						\
186121330Sharti		_s2 = TAILQ_NEXT(_s1, link);				\
187121330Sharti		SSCOP_MSG_FREE(_s1->msg);				\
188121330Sharti		SIG_FREE(_s1);						\
189121330Sharti		_s1 = _s2;						\
190121330Sharti	}								\
191121330Sharti	TAILQ_INIT(Q);							\
192121330Sharti    } while(0)
193121330Sharti
194121330Sharti
195121330Sharti
196121330Sharti/*
197121330Sharti * Message buffers
198121330Sharti */
199121330Sharti/* Free a buffer (if there is one) */
200121330Sharti#define	MBUF_FREE(M)	do { if(M) uni_msg_destroy(M); } while(0)
201121330Sharti
202121330Sharti/* duplicate a buffer */
203121330Sharti#define	MBUF_DUP(M) uni_msg_dup(M)
204121330Sharti
205121330Sharti/* compute current length */
206121330Sharti#define	MBUF_LEN(M) uni_msg_len((M))
207121330Sharti
208121330Sharti/*
209121330Sharti * Return the i-th word counted from the end of the buffer.
210121330Sharti * i=-1 will return the last 32bit word, i=-2 the 2nd last.
211121330Sharti * Assumes that there is enough space.
212121330Sharti */
213121330Sharti#define	MBUF_TRAIL32(M,I) uni_msg_trail32((M), (I))
214121330Sharti
215121330Sharti/*
216121330Sharti * Strip 32bit value from the end
217121330Sharti */
218121330Sharti#define	MBUF_STRIP32(M) uni_msg_strip32((M))
219121330Sharti
220121330Sharti/*
221121330Sharti * Strip 32bit value from head
222121330Sharti */
223121330Sharti#define	MBUF_GET32(M) uni_msg_get32((M))
224121330Sharti
225121330Sharti/*
226121330Sharti * Append a 32bit value to an mbuf. Failures are ignored.
227121330Sharti */
228121330Sharti#define	MBUF_APPEND32(M,W) uni_msg_append32((M), (W))
229121330Sharti
230121330Sharti/*
231121330Sharti * Pad a message to a multiple of four byte and return the amount of padding
232121330Sharti * Failures are ignored.
233121330Sharti */
234121330Sharti#define	MBUF_PAD4(M)							\
235121330Sharti    ({									\
236121330Sharti	int _npad = 0;							\
237121330Sharti	while (uni_msg_len(M) % 4 != 0) {				\
238121330Sharti		uni_msg_append8((M), 0);				\
239121330Sharti		_npad++;						\
240121330Sharti	}								\
241121330Sharti	_npad;								\
242121330Sharti    })
243121330Sharti
244121330Sharti#define	MBUF_UNPAD(M,P) do { (M)->b_wptr -= (P); } while(0)
245121330Sharti
246121330Sharti/*
247121330Sharti * Allocate a message that will probably hold N bytes.
248121330Sharti */
249121330Sharti#define	MBUF_ALLOC(N) uni_msg_alloc(N)
250121330Sharti
251121330Sharti#ifdef SSCOP_DEBUG
252121330Sharti#define	ASSERT(X)	assert(X)
253121330Sharti#else
254121330Sharti#define	ASSERT(X)
255121330Sharti#endif
256