1 /*	$Id$ */
2 /*
3  * Copyright (c) 1995-1996 Sam Leffler
4  * Copyright (c) 1995-1996 Silicon Graphics, Inc.
5  * HylaFAX is a trademark of Silicon Graphics
6  *
7  * Permission to use, copy, modify, distribute, and sell this software and
8  * its documentation for any purpose is hereby granted without fee, provided
9  * that (i) the above copyright notices and this permission notice appear in
10  * all copies of the software and related documentation, and (ii) the names of
11  * Sam Leffler and Silicon Graphics may not be used in any advertising or
12  * publicity relating to the software without the specific, prior written
13  * permission of Sam Leffler and Silicon Graphics.
14  *
15  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
17  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
18  *
19  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
20  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
21  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
22  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
23  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24  * OF THIS SOFTWARE.
25  */
26 #ifndef _Trigger_
27 #define	_Trigger_
28 /*
29  * HylaFAX Trigger Support.
30  */
31 #include "Str.h"
32 #include "Dictionary.h"
33 #include "QLink.h"
34 
35 #define	TRIGGER_MAXTID	1024	// at most 1024 triggers can exist at one time
36 #define	TRIGGER_BPW	32	// we assume 8*sizeof (u_int) >= 32
37 #define	TRIGGER_MAXWDS	((TRIGGER_MAXTID+TRIGGER_BPW-1)/TRIGGER_BPW)
38 
39 typedef struct {
40     char	magic;		// ``!''
41     char	reserved;	// reserved for future use
42     u_short	seqnum;		// per-client message sequence number
43     u_short	length;		// message length in bytes, including header
44     u_short	event;		// event number
45     time_t	tstamp;		// time message was crafted
46 } TriggerMsgHeader;
47 
48 typedef unsigned int TriggerEvent;
49 typedef unsigned int trid_t;
50 class HylaClient;
51 class Job;
52 class Modem;
53 class fxStackBuffer;
54 
55 /*
56  * Triggers represent client interest for events
57  * that occur within central scheduler (or which
58  * are passed back from subprocesses for distribution).
59  *
60  * Events are broken into classes and interest can
61  * be specified for specific events or for any events
62  * within a class.  Similarly, interest can be constrained
63  * to be specific to a particlar job or modem or for
64  * any job or modem.
65  *
66  * Clients create triggers and receive notification
67  * messages through FIFO special files whenever events
68  * occur that match the event interests specified.
69  */
70 class Trigger {
71 public:
72     enum {
73 #define	JOB_BASE	0
74 	JOB_CREATE	= JOB_BASE+0,	// creation
75 	JOB_SUSPEND	= JOB_BASE+1,	// suspended
76 	JOB_READY	= JOB_BASE+2,	// ready to send
77 	JOB_SLEEP	= JOB_BASE+3,	// sleeping awaiting time-to-send
78 	JOB_DEAD	= JOB_BASE+4,	// marked dead
79 	JOB_PROCESS	= JOB_BASE+5,	// processed by scheduler
80 	JOB_REAP	= JOB_BASE+6,	// corpus reaped
81 	JOB_ACTIVE	= JOB_BASE+7,	// activated
82 	JOB_REJECT	= JOB_BASE+8,	// rejected
83 	JOB_KILL	= JOB_BASE+9,	// killed
84 	JOB_BLOCKED	= JOB_BASE+10,	// blocked by other job
85 	JOB_DELAYED	= JOB_BASE+11,	// delayed by tod restriction or similar
86 	JOB_ALTERED	= JOB_BASE+12,	// parameters altered
87 	JOB_TIMEDOUT	= JOB_BASE+13,	// kill timer expired
88 	JOB_PREP_BEGIN	= JOB_BASE+14,	// preparation started
89 	JOB_PREP_END	= JOB_BASE+15,	// preparation finished
90 
91 #define	SEND_BASE	16
92 	SEND_BEGIN	= SEND_BASE+0,	// fax, send attempt started
93 	SEND_CALL	= SEND_BASE+1,	// fax, call placed
94 	SEND_CONNECTED	= SEND_BASE+2,	// fax, call answered by fax
95 	SEND_PAGE	= SEND_BASE+3,	// fax, page done
96 	SEND_DOC	= SEND_BASE+4,	// fax, document done
97 	SEND_POLLRCVD	= SEND_BASE+5,	// fax, document retrieved by poll op
98 	SEND_POLLDONE	= SEND_BASE+6,	// fax, poll op complete
99 	SEND_END	= SEND_BASE+7,	// fax, send attempt finished
100 	SEND_REFORMAT	= SEND_BASE+8,	// fax, job being reformatted
101 	SEND_REQUEUE	= SEND_BASE+9,	// fax, job requeued
102 	SEND_DONE	= SEND_BASE+10,	// fax, send job done
103 
104 #define	RECV_BASE	32
105 	RECV_BEGIN	= RECV_BASE+0,	// fax, inbound call started
106 	RECV_START	= RECV_BASE+1,	// fax, session started
107 	RECV_PAGE	= RECV_BASE+2,	// fax, page done
108 	RECV_DOC	= RECV_BASE+3,	// fax, document done
109 	RECV_END	= RECV_BASE+4,	// fax, inbound call finished
110 
111 #define	MODEM_BASE	48
112 	MODEM_ASSIGN	= MODEM_BASE+0,	// modem assigned to job
113 	MODEM_RELEASE	= MODEM_BASE+1,	// modem released by job
114 	MODEM_DOWN	= MODEM_BASE+2,	// modem marked down
115 	MODEM_READY	= MODEM_BASE+3,	// modem marked ready
116 	MODEM_BUSY	= MODEM_BASE+4,	// modem marked busy
117 	MODEM_WEDGED	= MODEM_BASE+5,	// modem considered wedged
118 	MODEM_INUSE	= MODEM_BASE+6,	// modem inuse for outbound work
119 	MODEM_DATA_BEGIN= MODEM_BASE+7,	// inbound data call begun
120 	MODEM_DATA_END	= MODEM_BASE+8,	// inbound data call finished
121 	MODEM_VOICE_BEGIN= MODEM_BASE+9,// inbound voice call begun
122 	MODEM_VOICE_END	= MODEM_BASE+10,// inbound voice call finished
123 	MODEM_CID	= MODEM_BASE+11	// inbound caller-ID information
124     };
125 #define	TRIGGER_MAXEVENT (MODEM_BASE+16)
126 private:
127     trid_t	tid;			// trigger ID
128     u_int	refs;			// count of references
129     u_short	interests[TRIGGER_MAXEVENT>>4];// bitmask of event interests
130     HylaClient*	client;			// reference to client
131 
132     static Trigger* triggers[TRIGGER_MAXTID];
133     static QLink wildcards[TRIGGER_MAXEVENT>>4];// for wildcard matches
134 
135     static u_int tidFree[TRIGGER_MAXWDS];
136     static u_int tidRotor;
137     static trid_t tidNextFree();
138 
139     static u_short hookInterests[TRIGGER_MAXEVENT>>4];	// bitmask of hook interests
140     static fxStr hookCmd;
141 
142     friend class TriggerRef;		// for access to reference count
143 
144     Trigger(trid_t, const fxStr& fifoName);
145 
146     bool parse(const char*);		// parse trigger spec
147     static void syntaxError(const char* spec, const char* msg);
148 
149     void purgeWildRefs();		// purge all wildcard references
150     bool cancel();
151 
152     static void post(TriggerEvent, const QLink&, const QLink&, fxStackBuffer&);
153     void send(const char* fmt ...);
154 
155     static void hook (TriggerEvent, const char* id, const char* info);
156 public:
157     ~Trigger();
158 
159     static void purgeClient(HylaClient*);// purge all triggers for client
160 
161     static void create(const fxStr& id, const char* spec);
162     static bool cancel(const char* tid);
163 
164     static void post(TriggerEvent, const Job&, const char* = NULL);
165     static void post(TriggerEvent, const Modem&, const char* = NULL);
166 
167     static bool setTriggerHook (const char* prg, const char* spec);
168 };
169 #endif /* _Trigger_ */
170