1 /*****************************************************************************\
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
10 \*****************************************************************************/
18 #include <sys/ioctl.h>
19 #include <sys/types.h>
26 * initialize h323 port
28 H323Port::H323Port(int type, char *portname, struct port_settings *settings) : Port(type, portname, settings)
30 p_h323_channel_in = p_h323_channel_out = NULL;
31 p_h323_connect = NULL;
33 /* configure device */
36 case PORT_TYPE_H323_IN:
38 case PORT_TYPE_H323_OUT:
39 SPRINT(p_name, "H323_outgoing_port_#%lu", p_serial);
42 if (options.law == 'u')
57 * endpoint sends messages to the interface
59 int H323Port::message_epoint(unsigned long epoint_id, int message_id, union parameter *param)
61 H323Connection *connection;
62 H323Connection::CallEndReason h323_cause;
63 char name[sizeof(p_name)];
65 if (Port::message_epoint(epoint_id, message_id, param))
70 case MESSAGE_mISDNSIGNAL: /* isdn command */
71 PDEBUG(DEBUG_H323, "H323Port(%s) mISDN signal not supported.\n", p_name);
74 case MESSAGE_INFORMATION: /* additional digits from endpoint */
75 PDEBUG(DEBUG_H323, "H323Port(%s) h323 port with (caller id %s) received more digit information: '%s'\n", p_name, p_callerinfo.id, param->information.number);
76 /* queue to be done */
77 if (p_state != PORT_STATE_OUT_OVERLAP)
79 PERROR("H323Port(%s) additinal digits are only possible in outgoing overlap state.\n", p_name);
82 if (strlen(param->information.number)>30)
84 PERROR("H323Port(%s) information string too long.\n", p_name);
87 SCAT((char *)p_dialinginfo.number, param->information.number);
90 case MESSAGE_PROCEEDING: /* call of endpoint is proceeding */
91 PDEBUG(DEBUG_H323, "H323Port(%s) h323 port with (caller id %s) received proceeding\n", p_name, p_callerinfo.id);
92 if (p_state != PORT_STATE_IN_OVERLAP)
94 PERROR("H323Port(%s) proceeding command only possible in setup state.\n", p_name);
97 p_state = PORT_STATE_IN_PROCEEDING;
100 case MESSAGE_ALERTING: /* call of endpoint is ringing */
101 PDEBUG(DEBUG_H323, "H323Port(%s) h323 port with (caller id %s) received alerting\n", p_name, p_callerinfo.id);
102 if (p_state != PORT_STATE_IN_OVERLAP
103 && p_state != PORT_STATE_IN_PROCEEDING)
105 PERROR("H323Port(%s) alerting command only possible in setup or proceeding state.\n", p_name);
108 p_state = PORT_STATE_IN_ALERTING;
111 connection = h323_ep->FindConnectionWithLock(name);
114 if (options.h323_ringconnect && !p_callerinfo.intern[0])
116 connection->AnsweringCall(H323Connection::AnswerCallNow);
117 p_state = PORT_STATE_CONNECT;
119 connection->AnsweringCall(H323Connection::AnswerCallPending);
120 connection->Unlock();
125 case MESSAGE_CONNECT: /* call of endpoint is connected */
126 PDEBUG(DEBUG_H323, "H323Port(%s) h323 port with (caller id %s) received connect\n", p_name, p_callerinfo.id);
127 if (p_state != PORT_STATE_IN_OVERLAP
128 && p_state != PORT_STATE_IN_PROCEEDING
129 && p_state != PORT_STATE_IN_ALERTING)
131 PDEBUG(DEBUG_H323, "H323Port(%s) connect command only possible in setup, proceeding or alerting state.\n", p_name);
134 new_state(PORT_STATE_CONNECT);
135 /* copy connected information */
136 memcpy(&p_connectinfo, ¶m->connectinfo, sizeof(p_connectinfo));
137 p_connectinfo.itype = INFO_ITYPE_H323;
140 connection = h323_ep->FindConnectionWithLock(name);
143 int type, present, screen;
144 PString connect_number;
145 /* modify connectinfo (COLP) */
146 if (p_connectinfo.present!=INFO_PRESENT_NULL)
148 connect_number = p_connectinfo.id;
149 switch(p_connectinfo.ntype)
151 case INFO_NTYPE_SUBSCRIBER:
152 type = Q931::SubscriberType;
154 case INFO_NTYPE_NATIONAL:
155 type = Q931::NationalType;
157 case INFO_NTYPE_INTERNATIONAL:
158 type = Q931::InternationalType;
160 default: /* INFO_TYPE_UNKNOWN */
161 type = Q931::UnknownType;
163 switch(p_connectinfo.present)
165 case INFO_PRESENT_RESTRICTED:
168 case INFO_PRESENT_NOTAVAIL:
171 default: /* INFO_PRESENT_ALLOWED */
174 switch(p_connectinfo.screen)
176 case INFO_SCREEN_USER:
179 default: /* INFO_SCREEN_NETWORK */
185 //PDEBUG(DEBUG_H323, "DDDEBUG: number %s, type=%d, present %d, screen %d\n", p_connectinfo.id, type, present, screen);
186 ((Q931 *)p_h323_connect)->SetConnectedNumber(connect_number, Q931::ISDNPlan, type, present, screen);
189 PERROR("missing p_h323_connect\n");
193 connection->AnsweringCall(H323Connection::AnswerCallNow);
194 connection->Unlock();
199 case MESSAGE_DISCONNECT: /* call has been disconnected */
201 PDEBUG(DEBUG_H323, "H323Port(%s) h323 port with (caller id %s) received disconnect cause=%d\n", p_name, p_callerinfo.id, param->disconnectinfo.cause);
202 /* we just play what we hear from the remote site */
203 if (p_state == PORT_STATE_IN_OVERLAP
204 || p_state == PORT_STATE_IN_PROCEEDING)
206 /* copy connected information */
207 memcpy(&p_connectinfo, ¶m->connectinfo, sizeof(p_connectinfo));
210 connection = h323_ep->FindConnectionWithLock(name);
213 connection->AnsweringCall(H323Connection::AnswerCallNow);
214 connection->Unlock();
218 new_state(PORT_STATE_DISCONNECT);
222 case MESSAGE_RELEASE: /* release h323 port */
223 PDEBUG(DEBUG_H323, "H323Port(%s) h323 port with (caller id %s) received disconnect cause=%d\n", p_name, p_callerinfo.id, param->disconnectinfo.cause);
224 if (p_state != PORT_STATE_IN_OVERLAP
225 && p_state != PORT_STATE_IN_PROCEEDING
226 && p_state != PORT_STATE_IN_ALERTING
227 && p_state != PORT_STATE_OUT_SETUP
228 && p_state != PORT_STATE_OUT_OVERLAP
229 && p_state != PORT_STATE_OUT_PROCEEDING
230 && p_state != PORT_STATE_OUT_ALERTING
231 && p_state != PORT_STATE_CONNECT)
233 PERROR("H323Port(%s) disconnect command only possible in setup, proceeding, alerting or connect state.\n", p_name);
237 switch(param->disconnectinfo.cause)
240 h323_cause = H323Connection::EndedByNoUser;
246 h323_cause = H323Connection::EndedByUnreachable;
250 h323_cause = H323Connection::EndedByRemoteBusy;
254 h323_cause = H323Connection::EndedByNoEndPoint;
258 h323_cause = H323Connection::EndedByNoAnswer;
262 h323_cause = H323Connection::EndedByRefusal;
266 h323_cause = H323Connection::EndedByHostOffline;
270 h323_cause = H323Connection::EndedByConnectFail;
274 h323_cause = H323Connection::EndedByCapabilityExchange;
278 h323_cause = H323Connection::EndedByRemoteCongestion;
282 h323_cause = H323Connection::EndedByTemporaryFailure;
286 h323_cause = H323Connection::EndedByRemoteUser;
291 h323_ep->ClearCall(name, h323_cause);
297 case MESSAGE_SETUP: /* dial-out command received from epoint */
298 PDEBUG(DEBUG_H323, "H323Port(%s) h323 port received setup from '%s' to '%s'\n", p_name, param->setup.callerinfo.id, param->setup.dialinginfo.number);
299 if (p_type!=PORT_TYPE_H323_OUT)
301 PERROR("H323Port(%s) cannot dial because h323 port not of outgoing type.\n", p_name);
304 if (p_state != PORT_STATE_IDLE)
306 PERROR("H323Port(%s) error: dialing command only possible in idle state.\n", p_name);
313 PERROR("H323Port(%s) software error: epoint pointer is set in idle state, how bad!! exitting.\n", p_name);
316 if (!(epointlist_new(epoint_id)))
318 PERROR("no memory for epointlist\n");
322 /* copy setup infos to port */
323 memcpy(&p_callerinfo, ¶m->setup.callerinfo, sizeof(p_callerinfo));
324 memcpy(&p_dialinginfo, ¶m->setup.dialinginfo, sizeof(p_dialinginfo));
325 memcpy(&p_capainfo, ¶m->setup.capainfo, sizeof(p_capainfo));
326 memcpy(&p_redirinfo, ¶m->setup.redirinfo, sizeof(p_redirinfo));
328 p_state = PORT_STATE_OUT_SETUP;
332 h323_ep->Call(name, param->setup.callerinfo.id, param->setup.dialinginfo.number);
337 PDEBUG(DEBUG_H323, "H323Port(%s) h323 port with (caller id %s) received an unsupported message: %d\n", p_name, p_callerinfo.id, message_id);