20
20
#include <signal.h>
21
21
#include "sipomatic.h"
26
27
Sipomatic sipomatic;
28
static char *num2str(int a)
31
snprintf(p,10,"%i",a);
29
int sipomatic_accept_audio_offer(sdp_context_t *ctx,sdp_payload_t *payload);
30
int sipomatic_accept_video_offer(sdp_context_t *ctx,sdp_payload_t *payload);
33
sdp_handler_t sipomatic_sdp_handler={
34
sipomatic_accept_audio_offer, /*from remote sdp */
35
sipomatic_accept_video_offer,
36
42
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*/
47
void sipomatic_process_event(Sipomatic *obj,eXosip_event_t *ev)
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);
52
call_new(obj,ev->did,ev->sdp_body);
54
case EXOSIP_CALL_CLOSED:
55
case EXOSIP_CALL_CANCELLED:
56
call=sipomatic_find_call(obj,ev->did);
58
ms_warning("Could not find call with did %i !",ev->did);
63
case EXOSIP_IN_SUBSCRIPTION_NEW:
64
ms_message("Receving new incoming subscription.");
65
eXosip_notify_accept_subscribe(ev->did,200,EXOSIP_SUBCRSTATE_ACTIVE,EXOSIP_NOTIFY_ONLINE);
70
eXosip_event_free(ev);
76
gint endoffile_cb(MSFilter *f,gint ev,gpointer arg,gpointer data)
78
Call*call=(Call*)data;
74
void endoffile_cb(void *ud, unsigned int ev,void * arg){
82
79
void call_accept(Call *call)
86
OsipDialog *dialog=call->dialog;
87
CallParams *callparams;
88
82
PayloadType *payload;
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);
84
static int call_count=0;
85
char record_file[250];
86
sprintf(record_file,"/tmp/sipomatic%i.wav",call_count);
89
payload=rtp_profile_get_payload(call->profile,call->audio.pt);
101
90
if (strcmp(payload->mime_type,"telephone-event")==0){
102
91
/* 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);
92
ms_message("Cannot accept call with only telephone-event.\n");
93
eXosip_answer_call(call->did,415,NULL);
105
94
call->state=CALL_STATE_FINISHED;
108
97
if (payload->clock_rate==16000){
109
98
hellofile=call->root->file_path16000hz;
110
99
}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);
100
eXosip_answer_call_with_body(call->did,200,"application/sdp",call->sdpc->answerstr);
101
call->audio_stream=audio_stream_start_with_files(call->profile,call->audio.localport,
102
call->audio.remaddr,call->audio.remoteport,call->audio.pt,20,hellofile,record_file);
105
if (call->video.remoteport!=0){
106
call->video_stream=video_stream_send_only_start(call->profile,call->video.localport,call->video.remaddr,
107
call->video.remoteport,call->video.pt,"/dev/video0");
110
call->time=time(NULL);
115
111
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)
112
ms_filter_set_notify_callback(call->audio_stream->soundread,endoffile_cb,(void*)call);
116
PayloadType * sipomatic_payload_is_supported(sdp_payload_t *payload,RtpProfile *local_profile,RtpProfile *dialog_profile)
130
119
if (payload->a_rtpmap!=NULL){
131
120
localpt=rtp_profile_get_payload_number_from_rtpmap(local_profile,payload->a_rtpmap);
133
122
localpt=payload->pt;
134
g_warning("payload has no rtpmap.");
123
ms_warning("payload has no rtpmap.");
139
127
/* this payload is supported in our local rtp profile, so add it to the dialog rtp
141
129
PayloadType *rtppayload;
142
130
rtppayload=rtp_profile_get_payload(local_profile,localpt);
143
if (rtppayload==NULL) return 0;
131
if (rtppayload==NULL) return NULL;
132
/*check if we have the appropriate coder/decoder for this payload */
133
if (strcmp(rtppayload->mime_type,"telephone-event")!=0) {
134
if (!ms_filter_codec_supported(rtppayload->mime_type)) {
135
ms_message("Codec %s is not supported.", rtppayload->mime_type);
144
139
rtppayload=payload_type_clone(rtppayload);
145
140
rtp_profile_set_payload(dialog_profile,payload->pt,rtppayload);
146
141
/* add to the rtp payload type some other parameters (bandwidth) */
147
142
if (payload->b_as_bandwidth!=0) rtppayload->normal_bitrate=payload->b_as_bandwidth*1000;
143
if (payload->a_fmtp!=NULL)
144
payload_type_set_send_fmtp(rtppayload,payload->a_fmtp);
145
if (strcasecmp(rtppayload->mime_type,"iLBC")==0){
146
/*default to 30 ms mode */
147
payload->a_fmtp="ptime=30";
148
payload_type_set_recv_fmtp(rtppayload,payload->a_fmtp);
152
int accept_audio_offer(SdpHandler *sdph,SdpContext *ctx,SdpPayload *payload)
155
int sipomatic_accept_audio_offer(sdp_context_t *ctx,sdp_payload_t *payload)
154
157
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;
158
Call *call=(Call*)sdp_context_get_user_pointer(ctx);
159
PayloadType *supported;
160
struct stream_params *params=&call->audio;
165
162
/* 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);
163
supported=sipomatic_payload_is_supported(payload,&av_profile,call->profile);
164
if (supported==NULL) {
165
ms_message("Refusing codec %i (%s)",payload->pt,payload->a_rtpmap);
171
if (callparams->ncodecs==0){
168
if (strcmp(supported->mime_type,"telephone-event")==0) return 0;
169
if (params->ncodecs==0 ){
172
170
/* 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++;
171
params->localport=payload->localport=audioport;
172
params->remoteport=payload->remoteport;
173
params->line=payload->line;
174
params->pt=payload->pt; /* remember the first payload accepted */
175
params->remaddr=payload->c_addr;
181
179
/* refuse all other audio lines*/
182
if(callparams->line!=payload->line) return -1;
187
void sipomatic_init(Sipomatic *obj, gchar *url)
180
if(params->line!=payload->line) return -1;
185
int sipomatic_accept_video_offer(sdp_context_t *ctx,sdp_payload_t *payload)
188
static int videoport=80000;
189
Call *call=(Call*)sdp_context_get_user_pointer(ctx);
190
PayloadType *supported;
191
struct stream_params *params=&call->video;
193
/* see if this codec is supported in our local rtp profile*/
194
supported=sipomatic_payload_is_supported(payload,&av_profile,call->profile);
195
if (supported==NULL) {
196
ms_message("Refusing video codec %i (%s)",payload->pt,payload->a_rtpmap);
199
if (params->ncodecs==0 ){
200
/* this is the first codec we may accept*/
201
params->localport=payload->localport=videoport;
202
params->remoteport=payload->remoteport;
203
params->line=payload->line;
204
params->pt=payload->pt; /* remember the first payload accepted */
205
params->remaddr=payload->c_addr;
209
/* refuse all other video lines*/
210
if(params->line!=payload->line) return -1;
218
void sipomatic_init(Sipomatic *obj, char *url, bool_t ipv6)
220
osip_uri_t *uri=NULL;
223
eXosip_enable_ipv6(ipv6);
193
226
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();
228
if (ipv6) url="sip:robot@[::1]:5064";
229
else url="sip:robot@127.0.0.1:5064";
234
if (osip_uri_parse(uri,url)==0){
235
if (uri->port!=NULL) port=atoi(uri->port);
237
ms_warning("Invalid identity uri:%s",url);
240
ms_message("Starting using url %s",url);
241
ms_mutex_init(&obj->lock,NULL);
200
243
obj->acceptance_time=5;
201
244
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);
245
obj->file_path8000hz=ms_strdup_printf("%s/%s",PACKAGE_SOUND_DIR,ANNOUCE_FILE8000HZ);
246
obj->file_path16000hz=ms_strdup_printf("%s/%s",PACKAGE_SOUND_DIR,ANNOUCE_FILE16000HZ);
247
osip_trace_initialize(OSIP_INFO1,stdout);
248
osip_trace_initialize(OSIP_INFO2,stdout);
249
osip_trace_initialize(OSIP_WARNING,stdout);
250
osip_trace_initialize(OSIP_ERROR,stdout);
251
osip_trace_initialize(OSIP_BUG,stdout);
252
osip_trace_initialize(OSIP_FATAL,stdout);
253
osip_trace_enable_level(OSIP_INFO1);
254
osip_trace_enable_level(OSIP_INFO2);
255
osip_trace_enable_level(OSIP_WARNING);
256
osip_trace_enable_level(OSIP_ERROR);
257
osip_trace_enable_level(OSIP_BUG);
258
osip_trace_enable_level(OSIP_FATAL);
259
eXosip_init(NULL,stdout,port);
260
eXosip_set_user_agent("sipomatic-" LINPHONE_VERSION "/eXosip");
222
263
void sipomatic_uninit(Sipomatic *obj)
224
g_mutex_free(obj->lock);
225
osip_ua_destroy(obj->ua);
265
ms_mutex_destroy(&obj->lock);
228
269
void sipomatic_iterate(Sipomatic *obj)
272
MSList *to_be_destroyed=NULL;
277
while((ev=eXosip_event_wait(0,0))!=NULL){
278
sipomatic_process_event(obj,ev);
235
281
while(elem!=NULL){
236
282
call=(Call*)elem->data;
237
time=g_timer_elapsed(call->timer,NULL);
283
elapsed=time(NULL)-call->time;
238
284
switch(call->state){
239
285
case CALL_STATE_INIT:
240
if (time>obj->acceptance_time){
286
if (elapsed>obj->acceptance_time){
241
287
call_accept(call);
244
290
case CALL_STATE_RUNNING:
245
if (time>obj->max_call_time || call->eof){
291
if (elapsed>obj->max_call_time || call->eof){
246
292
call_release(call);
247
elem=obj->calls=g_list_remove(obj->calls,call);
293
to_be_destroyed=ms_list_append(to_be_destroyed,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);
297
elem=ms_list_next(elem);
299
for(;to_be_destroyed!=NULL; to_be_destroyed=ms_list_next(to_be_destroyed)){
300
call_destroy((Call*)to_be_destroyed->data);
305
Call* sipomatic_find_call(Sipomatic *obj,int did)
309
for (it=obj->calls;it!=NULL;it=ms_list_next(it)){
310
call=(Call*)it->data;
311
if ( call->did==did) return call;
317
Call * call_new(Sipomatic *root, int did, char *sdp)
322
sdp_context_t *sdpc=sdp_handler_create_context(&sipomatic_sdp_handler,NULL,"sipomatic");
264
324
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;
325
eXosip_answer_call(did,100,NULL);
326
sdp_context_set_user_pointer(sdpc,obj);
327
sdpans=sdp_context_get_answer(sdpc,sdp);
329
eXosip_answer_call(did,180,NULL);
332
status=sdp_context_get_status(sdpc);
333
eXosip_answer_call(did,status,NULL);
334
sdp_context_free(sdpc);
335
rtp_profile_destroy(obj->profile);
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);
341
obj->time=time(NULL);
289
342
obj->audio_stream=NULL;
290
343
obj->state=CALL_STATE_INIT;
346
root->calls=ms_list_append(root->calls,obj);
295
350
void call_release(Call *call)
297
osip_dialog_bye(call->dialog);
352
eXosip_terminate_call(0,call->did);
353
if (call->audio_stream!=NULL) audio_stream_stop(call->audio_stream);
355
if (call->video_stream!=NULL) video_stream_send_only_stop(call->video_stream);
298
357
call->state=CALL_STATE_FINISHED;
301
360
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);
362
obj->root->calls=ms_list_remove(obj->root->calls,obj);
363
rtp_profile_destroy(obj->profile);
364
sdp_context_free(obj->sdpc);
309
368
void sipomatic_set_annouce_file(Sipomatic *obj, char *file)
311
370
if (obj->file_path8000hz!=NULL){
312
g_free(obj->file_path8000hz);
371
ms_free(obj->file_path8000hz);
314
obj->file_path8000hz=g_strdup(file);
373
obj->file_path8000hz=ms_strdup(file);
317
extern OsipManager *def_manager;
319
377
void display_help()