1 ///////////////////////////////////////////////////////////////////////////////
5 //---------------------------------------------------------------------------//
6 // Copyright: Andreas Eversberg //
10 ///////////////////////////////////////////////////////////////////////////////
15 The code was inspired by the isdn2h323 gateway my marco bode.
16 Thanx to marco budde for lerarning to program h323 and c++ from your code.
17 His homepage is www.telos.de, there you'll find the isdn2h323 gateway.
19 Also thanx to others who write documents and applications for OpenH323.
25 #include <sys/types.h>
29 //#include <gsmcodec.h>
30 //#include <g7231codec.h>
31 //#include <g729codec.h>
32 //#include "g726codec.h"
33 //#include <speexcodec.h>
42 H323_ep::H323_ep(void)
44 terminalType = e_GatewayOnly;
46 PDEBUG(DEBUG_H323, "H323 endpoint constuctor\n");
54 // clear all calls to remote endpoints
57 PDEBUG(DEBUG_H323, "H323 endpoint destuctor\n");
64 H323Connection *H323_ep::CreateConnection(unsigned callReference)
66 PDEBUG(DEBUG_H323, "H323 endpoint create connection\n");
68 return new H323_con(*this, callReference);
73 // on establishment of conneciton
75 void H323_ep::OnConnectionEstablished(H323Connection &connection, const PString &token)
77 const unsigned char *token_string = token;
79 PDEBUG(DEBUG_H323, "H323 endpoint connection established to: %s\n", token_string);
81 H323EndPoint::OnConnectionEstablished(connection, token);
87 BOOL H323_ep::OnAlerting(H323Connection &connection, const H323SignalPDU &alertingPDU, const PString &user)
90 const unsigned char *token_string = connection.GetCallToken();
91 const unsigned char *user_string = user;
92 struct message *message;
94 PDEBUG(DEBUG_H323, "H323 endpoint alerting at: %s\n", user_string);
98 if (!(port=(class H323Port *)find_port_with_token((char *)token_string)))
100 PERROR("cannot find port with token '%s'\n", token_string);
104 if (port->p_state==PORT_STATE_OUT_SETUP
105 || port->p_state==PORT_STATE_OUT_OVERLAP
106 || port->p_state==PORT_STATE_OUT_PROCEEDING)
108 port->new_state(PORT_STATE_OUT_ALERTING);
109 message = message_create(port->p_serial, ACTIVE_EPOINT(port->p_epointlist), PORT_TO_EPOINT, MESSAGE_ALERTING);
110 message_put(message);
120 // on clearing of connection
122 void H323_ep::OnConnectionCleared(H323Connection &connection, const PString &token)
125 class H323Port *port;
126 const unsigned char *token_string = token;
127 struct message *message;
129 PDEBUG(DEBUG_H323, "H323 endpoint connection cleared.\n");
133 if (!(port=(class H323Port *)find_port_with_token((char *)token_string)))
135 PERROR("cannot find port with token '%s'\n", token_string);
140 switch(connection.GetCallEndReason())
142 case H323Connection::EndedByRemoteUser:
143 case H323Connection::EndedByCallerAbort:
144 case H323Connection::EndedByGatekeeper:
145 case H323Connection::EndedByCallForwarded:
146 cause = 16; // normal call clearing
149 case H323Connection::EndedByRefusal:
150 case H323Connection::EndedBySecurityDenial:
151 cause = 21; // call rejected
154 case H323Connection::EndedByNoAnswer:
155 cause = 19; // no answer from user
158 case H323Connection::EndedByTransportFail:
159 cause = 47; // resource unavaiable, unspecified
162 case H323Connection::EndedByNoBandwidth:
163 cause = 49; // quality of service not available
166 case H323Connection::EndedByNoUser:
167 cause = 1; // unallocated number
170 case H323Connection::EndedByCapabilityExchange:
171 cause = 65; // bearer capability not implemented
174 case H323Connection::EndedByRemoteBusy:
175 cause = 17; // user busy
178 case H323Connection::EndedByRemoteCongestion:
179 cause = 42; // switching equipment congestion
182 case H323Connection::EndedByUnreachable:
183 cause = 2; // no route ...
186 case H323Connection::EndedByNoEndPoint:
187 case H323Connection::EndedByConnectFail:
188 cause = 18; // no user responding
191 case H323Connection::EndedByHostOffline:
192 cause = 27; // destination out of order
195 case H323Connection::EndedByTemporaryFailure:
196 cause = 41; // temporary failure
200 cause = 31; // normal, unspecified
206 if (port->p_h323_channel_in)
207 delete port->p_h323_channel_in;
208 port->p_h323_channel_in = NULL;
209 if (port->p_h323_channel_out)
210 delete port->p_h323_channel_out;
211 port->p_h323_channel_out = NULL;
213 /* release endpoint */
214 message = message_create(port->p_serial, ACTIVE_EPOINT(port->p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
215 message->param.disconnectinfo.cause = cause;
216 message->param.disconnectinfo.location = LOCATION_BEYOND;
217 message_put(message);
227 // open audio channel
229 BOOL H323_ep::OpenAudioChannel(H323Connection &connection, BOOL isEncoding, unsigned bufferSize, H323AudioCodec &codec)
232 class H323Port *port;
233 const unsigned char *token_string = connection.GetCallToken();
235 PDEBUG(DEBUG_H323, "H323 endpoint audio channel open (isEndcoding=%d).\n", isEncoding);
237 // disable the silence detection
238 codec.SetSilenceDetectionMode (H323AudioCodec::NoSilenceDetection);
243 channel = new H323_chan(connection.GetCallToken(), TRUE);
246 channel = new H323_chan(connection.GetCallToken(), FALSE);
250 PERROR("channel for token '%s' not set", token_string);
254 // return the channel object
256 if (!(port=(class H323Port *)find_port_with_token((char *)token_string)))
258 PERROR("cannot find port with token '%s'\n", token_string);
266 port->p_h323_channel_out = channel;
269 port->p_h323_channel_in = channel;
273 return codec.AttachChannel(channel, FALSE);
278 // open video channel
280 BOOL H323_ep::OpenVideoChannel(H323Connection &connection, BOOL isEncoding, H323VideoCodec &codec)
282 PDEBUG(DEBUG_H323, "H323 endpoint video channel open (isEndcoding=%d).\n", isEncoding);
290 // initialize H323 endpoint
292 BOOL H323_ep::Init(void)
294 H323ListenerTCP *listener;
297 PDEBUG(DEBUG_H323, "H323 endpoint initialize\n");
299 // add keypad capability
300 H323_UserInputCapability::AddAllCapabilities(capabilities, 0, P_MAX_INDEX);
302 /* will add codec in order of priority 1 = highest, 0 = don't use */
306 #warning codecs are temporarily disabled due to api change
308 if (options.h323_gsm_pri == pri)
310 H323_GSM0610Capability * gsm_cap;
311 MicrosoftGSMAudioCapability * msgsm_cap;
313 SetCapability(0, 0, gsm_cap = new H323_GSM0610Capability);
314 gsm_cap->SetTxFramesInPacket(options.h323_gsm_opt);
315 SetCapability(0, 0, msgsm_cap = new MicrosoftGSMAudioCapability);
316 msgsm_cap->SetTxFramesInPacket(options.h323_gsm_opt);
318 if (options.h323_g726_pri == pri)
320 if (options.h323_g726_opt > 4)
321 SetCapability(0, 0, new H323_G726_Capability(*this, H323_G726_Capability::e_40k));
322 if (options.h323_g726_opt > 3)
323 SetCapability(0, 0, new H323_G726_Capability(*this, H323_G726_Capability::e_32k));
324 if (options.h323_g726_opt > 2)
325 SetCapability(0, 0, new H323_G726_Capability(*this, H323_G726_Capability::e_24k));
326 SetCapability(0, 0, new H323_G726_Capability(*this, H323_G726_Capability::e_16k));
328 if (options.h323_g7231_pri == pri)
331 SetCapability(0, 0, new H323_G7231Capability(FALSE));
334 if (options.h323_g729a_pri == pri)
337 SetCapability(0, 0, new H323_G729Capability());
340 if (options.h323_lpc10_pri == pri)
342 SetCapability(0, 0, new H323_LPC10Capability(*this));
344 if (options.h323_speex_pri == pri)
346 if (options.h323_speex_opt > 5)
347 SetCapability(0, 0, new SpeexNarrow6AudioCapability());
348 if (options.h323_speex_opt > 4)
349 SetCapability(0, 0, new SpeexNarrow5AudioCapability());
350 if (options.h323_speex_opt > 3)
351 SetCapability(0, 0, new SpeexNarrow4AudioCapability());
352 if (options.h323_speex_opt > 2)
353 SetCapability(0, 0, new SpeexNarrow3AudioCapability());
354 SetCapability(0, 0, new SpeexNarrow2AudioCapability());
356 if (options.h323_xspeex_pri == pri)
358 if (options.h323_xspeex_opt > 5)
359 SetCapability(0, 0, new XiphSpeexNarrow6AudioCapability());
360 if (options.h323_xspeex_opt > 4)
361 SetCapability(0, 0, new XiphSpeexNarrow5AudioCapability());
362 if (options.h323_xspeex_opt > 3)
363 SetCapability(0, 0, new XiphSpeexNarrow4AudioCapability());
364 if (options.h323_xspeex_opt > 2)
365 SetCapability(0, 0, new XiphSpeexNarrow3AudioCapability());
366 SetCapability(0, 0, new XiphSpeexNarrow2AudioCapability());
369 if (options.h323_law_pri == pri)
371 H323_G711Capability * g711uCap;
372 H323_G711Capability * g711aCap;
373 SetCapability(0, 0, g711uCap = new H323_G711Capability (H323_G711Capability::ALaw/*, H323_G711Capability::At64k*/));
374 #warning H323_law frame size is disabled due to bug in OpenH323
375 // g711uCap->SetTxFramesInPacket(options.h323_law_opt);
376 SetCapability(0, 0, g711aCap = new H323_G711Capability (H323_G711Capability::muLaw/*, H323_G711Capability::At64k*/));
377 // g711aCap->SetTxFramesInPacket(options.h323_law_opt);
382 // h323 user is the hostname or given by h323_name
383 if (options.h323_name[0] == '\0')
385 if (getenv("HOSTNAME") == NULL)
387 cout << "OpenH323: Environment variable HOSTNAME not set. Please specify 'h323_name' in options.conf" << endl;
391 SetLocalUserName((options.h323_name[0])?options.h323_name:getenv("HOSTNAME"));
394 if (options.h323_icall)
396 PIPSocket::Address interfaceAddress(INADDR_ANY);
397 listener = new H323ListenerTCP(*this, interfaceAddress, options.h323_port);
398 if (!StartListener(listener))
400 cout << "OpenH323: Could not open H323 port " << listener->GetListenerPort() << endl;
403 cout << "OpenH323: Waiting for incoming H323 connections on port " << listener->GetListenerPort() << endl;
406 // register with gatekeeper
407 if (options.h323_gatekeeper)
409 if (options.h323_gatekeeper_host[0] == '\0')
411 if (DiscoverGatekeeper(new H323TransportUDP(*this)))
413 cout << "OpenH323: Registering with gatekeeper " << gatekeeper->GetIdentifier() << " (automatically)" << endl;
416 cout << "OpenH323: Gatekeeper not found." << endl;
421 if (SetGatekeeper(options.h323_gatekeeper_host) == TRUE)
423 cout << "OpenH323: Registering with gatekeeper " << gatekeeper->GetIdentifier() << " (automatically)" << endl;
426 cout << "OpenH323: Gatekeeper at " << gatekeeper->GetIdentifier() << " not found." << endl;
437 // make an outgoing h323 call
440 BOOL H323_ep::Call(char *token_string, char *caller, char *host)
445 class H323Port *port;
446 struct message *message;
447 char *newtoken_string;
449 PDEBUG(DEBUG_H323, "H323 endpoint call to host '%s'\n", host);
453 if (!MakeCall(address, token))
455 PDEBUG(DEBUG_H323, "H323 endpoint call to host '%s'\n", host);
461 if (!(port=(class H323Port *)find_port_with_token((char *)token_string)))
463 PERROR("cannot find port with token '%s'\n", token_string);
469 PDEBUG(DEBUG_H323, "call of port '%s' failed.\n", token_string);
470 message = message_create(port->p_serial, ACTIVE_EPOINT(port->p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
471 message->param.disconnectinfo.cause = 31;
472 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
473 message_put(message);
476 PDEBUG(DEBUG_H323, "changing port name from '%s' to token '%s'\n", token_string, token.GetPointer());
477 newtoken_string = token.GetPointer();
478 SCPY(port->p_name, newtoken_string);
481 PDEBUG(DEBUG_H323, "H323 endpoint call to host '%s'\n", host);
488 void H323_ep::SetEndpointTypeInfo(H225_EndpointType &info) const
490 // H225_VoiceCaps voicecaps;
491 PDEBUG(DEBUG_H323, "H323 endpoint set endpoint type info *TBD*\n");
493 H323EndPoint::SetEndpointTypeInfo(info);
495 // protocols.SetTag(H225_SupportedProtocols::e_voice);
496 // (H225_VoiceCaps&)protocols = voicecaps;
497 // a_protocols.SetSize(1);
498 // a_protocols[0] = protocols;
500 // gateway.IncludeOptionalField(H225_GatewayInfo::e_protocol);
501 // gateway.m_protocol = a_protocols;
502 // info.m_gateway = gateway;