1
/***************************************************************************
3
This is a test program for linphone. It acts as a sip server and answers to linphone's
7
copyright : (C) 2001 by Simon MORLAT
8
email : simon.morlat@linphone.org
9
***************************************************************************/
11
/***************************************************************************
13
* This program is free software; you can redistribute it and/or modify *
14
* it under the terms of the GNU General Public License as published by *
15
* the Free Software Foundation; either version 2 of the License, or *
16
* (at your option) any later version. *
18
***************************************************************************/
21
#include "sipomatic.h"
28
static char *num2str(int a)
31
snprintf(p,10,"%i",a);
36
void stop_handler(int signum)
41
int invite_accepted_cb(OsipDialog *call,transaction_t *trn, sip_t *msg,void *p2)
43
/* we should never be here since sipomatic is unable to to make invites*/
47
int bye_cb(OsipDialog *dialog,transaction_t *trn, sip_t *msg,void *p2)
50
Call *call=(Call*)dialog->data;
51
sipomatic_lock(&sipomatic);
52
if ( sipomatic_check_call(&sipomatic,call))
53
call->state=CALL_STATE_FINISHED;
54
sipomatic_unlock(&sipomatic);
58
int invite_cb(OsipDialog *dialog,transaction_t *trn, sip_t *sipmsg,void *p2)
60
/* we have just received an invite, so wait two seconds, then accept it*/
64
from_2char(sipmsg->from,&p);
65
g_message("Contacted by %s.\n",p);
67
call=call_new(dialog);
68
call->current_trn=trn;
69
call->root=&sipomatic;
70
sipomatic_lock(&sipomatic);
71
sipomatic.calls=g_list_append(sipomatic.calls,call);
72
sipomatic_unlock(&sipomatic);
76
gint endoffile_cb(MSFilter *f,gint ev,gpointer arg,gpointer data)
78
Call*call=(Call*)data;
82
void call_accept(Call *call)
86
OsipDialog *dialog=call->dialog;
87
CallParams *callparams;
91
ctx=SDP_CONTEXT(osip_dialog_get_body_context(dialog,"application/sdp",0));
92
callparams=(CallParams*)BODY_CONTEXT(ctx)->data;
93
status=sdp_context_get_negociation_status(ctx);
95
g_message("Error during sdp negociation, cannot accept call.\n");
96
osip_dialog_respond(dialog,call->current_trn,SDP_CONTEXT(ctx)->negoc_status);
97
call->state=CALL_STATE_FINISHED;
100
payload=rtp_profile_get_payload(callparams->profile,callparams->pt);
101
if (strcmp(payload->mime_type,"telephone-event")==0){
102
/* telephone-event is not enough to accept a call */
103
g_message("Cannot accept call with only telephone-event.\n");
104
osip_dialog_respond(dialog,call->current_trn,415);
105
call->state=CALL_STATE_FINISHED;
108
if (payload->clock_rate==16000){
109
hellofile=call->root->file_path16000hz;
110
}else hellofile=call->root->file_path8000hz;
111
osip_dialog_accept_invite(dialog,call->current_trn);
112
call->audio_stream=audio_stream_start_with_files(callparams->profile,callparams->localport,
113
callparams->remaddr,callparams->remoteport,callparams->pt,20,hellofile,"/dev/null",NULL);
114
g_timer_reset(call->timer);
115
call->state=CALL_STATE_RUNNING;
116
call->params=callparams;
117
ms_filter_set_notify_func(call->audio_stream->soundread,endoffile_cb,(gpointer)call);
121
int faillure_cb(OsipDialog *call,transaction_t *trn, sip_t *msg,void *p2)
127
int payload_is_supported(SdpPayload *payload,RtpProfile *local_profile,RtpProfile *dialog_profile)
130
if (payload->a_rtpmap!=NULL){
131
localpt=rtp_profile_get_payload_number_from_rtpmap(local_profile,payload->a_rtpmap);
134
g_warning("payload has no rtpmap.");
139
/* this payload is supported in our local rtp profile, so add it to the dialog rtp
141
PayloadType *rtppayload;
142
rtppayload=rtp_profile_get_payload(local_profile,localpt);
143
if (rtppayload==NULL) return 0;
144
rtppayload=payload_type_clone(rtppayload);
145
rtp_profile_set_payload(dialog_profile,payload->pt,rtppayload);
146
/* add to the rtp payload type some other parameters (bandwidth) */
147
if (payload->b_as_bandwidth!=0) rtppayload->normal_bitrate=payload->b_as_bandwidth*1000;
152
int accept_audio_offer(SdpHandler *sdph,SdpContext *ctx,SdpPayload *payload)
154
static int audioport=8000;
155
OsipDialog *dialog=BODY_CONTEXT(ctx)->dialog;
156
CallParams *callparams;
158
if (BODY_CONTEXT(ctx)->data!=NULL){
159
callparams=(CallParams *) BODY_CONTEXT(ctx)->data;
161
callparams=call_params_new();
162
BODY_CONTEXT(ctx)->data=(void*)callparams;
165
/* see if this codec is supported in our local rtp profile*/
166
supported=payload_is_supported(payload,&av_profile,callparams->profile);
168
g_message("Refusing codec %i (%s)",payload->pt,payload->a_rtpmap);
171
if (callparams->ncodecs==0){
172
/* this is the first codec we may accept*/
173
callparams->localport=payload->localport=audioport;
174
callparams->remoteport=payload->remoteport;
175
callparams->line=payload->line;
176
callparams->pt=payload->pt; /* remember the first payload accepted */
177
callparams->remaddr=payload->c_addr;
178
callparams->ncodecs++;
181
/* refuse all other audio lines*/
182
if(callparams->line!=payload->line) return -1;
187
void sipomatic_init(Sipomatic *obj, gchar *url)
193
url=getenv("SIPOMATIC_URL");
194
if (url==NULL) url="sip:robot@0.0.0.0:5064";
196
g_message("Starting using url %s",url);
197
obj->audio_codecs=ms_codec_get_all_audio();
198
obj->lock=g_mutex_new();
200
obj->acceptance_time=5;
201
obj->max_call_time=300;
202
obj->file_path8000hz=g_strdup_printf("%s/%s",PACKAGE_SOUND_DIR,ANNOUCE_FILE8000HZ);
203
obj->file_path16000hz=g_strdup_printf("%s/%s",PACKAGE_SOUND_DIR,ANNOUCE_FILE16000HZ);
205
/* create a user agent */
206
obj->ua=osip_ua_new();
207
osip_ua_set_contact(obj->ua,url);
208
osip_ua_signal_connect(obj->ua,"INVITE_ACCEPTED",invite_accepted_cb);
209
osip_ua_signal_connect(obj->ua,"BYE",bye_cb);
210
osip_ua_signal_connect(obj->ua,"FAILLURE",faillure_cb);
211
osip_ua_signal_connect(obj->ua,"INVITE",invite_cb);
212
/* add sdp capabilities to the user agent */
213
sdph=sdp_handler_new();
214
sdp_handler_set_write_offer_fcn(SDP_HANDLER(sdph),NULL,NULL);
215
sdp_handler_set_accept_offer_fcn(SDP_HANDLER(sdph),accept_audio_offer,NULL);
216
sdp_handler_set_read_answer_fcn(SDP_HANDLER(sdph),NULL,NULL);
218
osip_ua_add_body_handler(obj->ua,sdph);
222
void sipomatic_uninit(Sipomatic *obj)
224
g_mutex_free(obj->lock);
225
osip_ua_destroy(obj->ua);
228
void sipomatic_iterate(Sipomatic *obj)
236
call=(Call*)elem->data;
237
time=g_timer_elapsed(call->timer,NULL);
239
case CALL_STATE_INIT:
240
if (time>obj->acceptance_time){
244
case CALL_STATE_RUNNING:
245
if (time>obj->max_call_time || call->eof){
247
elem=obj->calls=g_list_remove(obj->calls,call);
251
case CALL_STATE_FINISHED:
252
elem=obj->calls=g_list_remove(obj->calls,call);
256
elem=g_list_next(elem);
258
sipomatic_unlock(obj);
261
CallParams * call_params_new(){
263
obj=g_new0(CallParams,1);
264
obj->profile=rtp_profile_new("remote");
267
void call_params_destroy(CallParams *obj)
269
rtp_profile_destroy(obj->profile);
273
gboolean sipomatic_check_call(Sipomatic *obj,Call *call)
276
for (it=obj->calls;it!=NULL;it=g_list_next(it)){
277
if ( ((Call*)it->data)==call) return 1;
282
Call * call_new(OsipDialog *dialog)
284
Call *obj=g_new0(Call,1);
285
obj->timer=g_timer_new();
287
dialog->data=(void*)obj;
288
g_timer_start(obj->timer);
289
obj->audio_stream=NULL;
290
obj->state=CALL_STATE_INIT;
295
void call_release(Call *call)
297
osip_dialog_bye(call->dialog);
298
call->state=CALL_STATE_FINISHED;
301
void call_destroy(Call *obj)
303
if (obj->audio_stream!=NULL) audio_stream_stop(obj->audio_stream);
304
g_timer_destroy(obj->timer);
305
if (obj->params!=NULL) call_params_destroy(obj->params);
309
void sipomatic_set_annouce_file(Sipomatic *obj, char *file)
311
if (obj->file_path8000hz!=NULL){
312
g_free(obj->file_path8000hz);
314
obj->file_path8000hz=g_strdup(file);
317
extern OsipManager *def_manager;
321
printf("sipomatic [-u sip-url] [-f annouce-file ] [-s port]\n"
322
"sipomatic -h or --help: display this help.\n"
323
"sipomatic -v or --version: display version information.\n"
324
" -u sip-url : specify the sip url sipomatic listens and answers.\n"
325
" -f annouce-file : set the annouce file (16 bit raw format,8000Hz)\n"
326
" -s port : set the port sipomatic uses to send its SIP answers.\n");
330
char *getarg(int argc, char*argv[], int i)
338
int main(int argc, char *argv[])
346
if ( (strcmp(argv[i],"-h")==0) || (strcmp(argv[i],"--help")==0) ){
350
if ( (strcmp(argv[i],"-v")==0) || (strcmp(argv[i],"--version")==0) ){
351
printf("version: " LINPHONE_VERSION "\n");
354
if (strcmp(argv[i],"-u")==0){
356
url=getarg(argc,argv,i);
359
if (strcmp(argv[i],"-s")==0){
362
port=getarg(argc,argv,i);
366
if (strcmp(argv[i],"-f")==0){
368
file=getarg(argc,argv,i);
373
signal(SIGINT,stop_handler);
375
ms_speex_codec_init();
377
ortp_set_debug_file("oRTP",NULL);
378
rtp_profile_set_payload(&av_profile,115,&lpc1015);
379
rtp_profile_set_payload(&av_profile,110,&speex_nb);
380
rtp_profile_set_payload(&av_profile,111,&speex_wb);
381
rtp_profile_set_payload(&av_profile,101,&telephone_event);
382
rtp_profile_set_payload(&av_profile,116,&truespeech);
383
TRACE_INITIALIZE(TRACE_LEVEL6,stdout);
385
osip_manager_set_send_port(def_manager,sendport);
386
sipomatic_init(&sipomatic,url);
387
if (file!=NULL) sipomatic_set_annouce_file(&sipomatic,file);
390
sipomatic_iterate(&sipomatic);