void call_release(Call *call) { eXosip_call_terminate(0,call->did); if (call->audio_stream!=NULL) audio_stream_stop(call->audio_stream); #ifdef VIDEO_ENABLED if (call->video_stream!=NULL) video_stream_send_only_stop(call->video_stream); #endif call->state=CALL_STATE_FINISHED; }
int uac_bye(const sessionId Id) { eXosip_lock(); eXosip_call_terminate( Id.cid, Id.did); eXosip_unlock(); eXosip_event_t *g_event = NULL;/*消息事件*/ uac_waitfor(&Id,EXOSIP_CALL_MESSAGE_ANSWERED,&g_event); if(!g_event) { printf("no bye response\n"); return 0; } eXosip_event_free (g_event); return 1; }
void eXosip_retransmit_lost200ok() { eXosip_call_t *jc; eXosip_dialog_t *jd; time_t now; now = time (NULL); for (jc = eXosip.j_calls; jc != NULL; jc = jc->next) { if (jc->c_id >= 1 && jc->c_dialogs != NULL) { for (jd = jc->c_dialogs; jd != NULL; jd = jd->next) { if (jd->d_id >=1 && jd->d_dialog != NULL && jd->d_200Ok!=NULL) { if (jd->d_count==5) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: no ACK received during 20s: dropping call\n")); /* hard for users to detect than I sent this BYE... */ jd->d_count=0; osip_message_free(jd->d_200Ok); jd->d_200Ok=NULL; eXosip_call_terminate(jc->c_id, jd->d_id); } else if (jd->d_timer<now) { /* a dialog exist: retransmit lost 200ok */ jd->d_timer = time (NULL) + 4; jd->d_count++; jd = jc->c_dialogs; /* TU retransmission */ cb_snd_message (NULL, jd->d_200Ok, NULL,0, -1); } } } } } return; }
/* temp implementation */ int serial_in_block(int fd, unsigned char s[], int length) { unsigned char i[2]; unsigned char j; int actual_length; if ( (2 != read (fd, i, 2)) || ((i[0] != 0x9A)&&(i[0] != 0x99)) || (i[1] != length)) { // printf("read error!\n"); return -1; } if (i[0] == 0x99) { if ((1 == read (fd, i ,1) && (i[0] == 0x03))) { eXosip_lock (); j = eXosip_call_terminate (calls.cid, calls.did); if (j == 0) call_remove (); eXosip_unlock (); calls.enable_audio = -1; } return -1; } actual_length = read(fd, s, length); if (actual_length != length) { printf("read error!\n"); return -1; } if ( (1 != read(fd, &j, 1)) || (j != count_crc8(i, 2, 0)) ) { printf("crc error!\n"); return -1; } return actual_length; }
int main (int argc, char *argv[]) { eXosip_event_t *je; osip_message_t *reg = NULL; osip_message_t *invite = NULL; osip_message_t *ack = NULL; osip_message_t *info = NULL; osip_message_t *message = NULL; int call_id, dialog_id; int i,flag; int flag1 = 1; int id; char *identity = "sip:[email protected]"; char *registerer = "sip:192.168.44.100:5060"; char *source_call = "sip:[email protected]"; char *dest_call = "sip:[email protected]:5060"; char command; char tmp[4096]; char localip[128]; printf("r 向服务器注册\n\n"); printf("c 取消注册\n\n"); printf("i 发起呼叫请求\n\n"); printf("h 挂断\n\n"); printf("q 退出程序\n\n"); printf("s 执行方法INFO\n\n"); printf("m 执行方法MESSAGE\n\n"); //初始化 i = eXosip_init (); if (i != 0) { printf ("Couldn't initialize eXosip!\n"); return -1; } else { printf ("eXosip_init successfully!\n"); } i = eXosip_listen_addr (IPPROTO_UDP, NULL, 5060, AF_INET, 0); if (i != 0) { eXosip_quit (); fprintf (stderr, "Couldn't initialize transport layer!\n"); return -1; } flag = 1; while (flag) { printf ("please input the comand:\n"); scanf ("%c", &command); getchar (); switch (command) { case 'r': printf ("This modal isn't commpleted!\n"); break; case 'i':/* INVITE */ i = eXosip_call_build_initial_invite (&invite, dest_call, source_call, NULL, "This si a call for a conversation"); if (i != 0) { printf ("Intial INVITE failed!\n"); break; } //符合SDP格式,其中属性a是自定义格式,也就是说可以存放自己的信息,但是只能是两列,比如帐户信息 //但是经测试,格式:v o t必不可少,原因未知,估计是协议栈在传输时需要检查的 snprintf (tmp, 4096, "v=0\r\n" "o=anonymous 0 0 IN IP4 0.0.0.0\r\n" "t=1 10\r\n" "a=username:rainfish\r\n" "a=password:123\r\n"); osip_message_set_body (invite, tmp, strlen(tmp)); osip_message_set_content_type (invite, "application/sdp"); eXosip_lock (); i = eXosip_call_send_initial_invite (invite); eXosip_unlock (); flag1 = 1; while (flag1) { je = eXosip_event_wait (0, 200); if (je == NULL) { printf ("No response or the time is over!\n"); break; } switch (je->type) { case EXOSIP_CALL_INVITE: printf ("a new invite reveived!\n"); break; case EXOSIP_CALL_PROCEEDING: printf ("proceeding!\n"); break; case EXOSIP_CALL_RINGING: printf ("ringing!\n"); // call_id = je->cid; // dialog_id = je->did; printf ("call_id is %d, dialog_id is %d \n", je->cid, je->did); break; case EXOSIP_CALL_ANSWERED: printf ("ok! connected!\n"); call_id = je->cid; dialog_id = je->did; printf ("call_id is %d, dialog_id is %d \n", je->cid, je->did); eXosip_call_build_ack (je->did, &ack); eXosip_call_send_ack (je->did, ack); flag1 = 0; break; case EXOSIP_CALL_CLOSED: printf ("the other sid closed!\n"); break; case EXOSIP_CALL_ACK: printf ("ACK received!\n"); break; default: printf ("other response!\n"); break; } eXosip_event_free (je); } break; case 'h': printf ("Holded !\n"); eXosip_lock (); eXosip_call_terminate (call_id, dialog_id); eXosip_unlock (); break; case 'c': printf ("This modal isn't commpleted!\n"); break; case 's': //传输INFO方法 eXosip_call_build_info (dialog_id, &info); snprintf (tmp , 4096, "hello,rainfish"); osip_message_set_body (info, tmp, strlen(tmp)); //格式可以任意设定,text/plain代表文本信息 osip_message_set_content_type (info, "text/plain"); eXosip_call_send_request (dialog_id, info); break; case 'm': //传输MESSAGE方法,也就是即时消息,和INFO方法相比,我认为主要区别,是MESSAGE不用建立连接,直接传输信息,而INFO必须 //在建立INVITE的基础上传输。 printf ("the mothed :MESSAGE\n"); eXosip_message_build_request (&message, "MESSAGE", dest_call, source_call, NULL); snprintf (tmp, 4096, "hellor rainfish"); osip_message_set_body (message, tmp, strlen(tmp)); //假设格式是xml osip_message_set_content_type (message, "text/xml"); eXosip_message_send_request (message); break; case 'q': eXosip_quit (); printf ("Exit the setup!\n"); flag = 0; break; } } return (0); }