www.gusucode.com > 嵌入式linux系统的网络编程源码程序 > 嵌入式linux系统的网络编程源码程序/视频会议源码/network_ctrl_recv_thread.cpp
/////////////////////////////////////////////////////// // FileName: network_ctrl_recv_thread.cpp // Author: b1gm0use // Project: myvideo #include <iostream> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <netinet/in.h> #include <arpa/inet.h> #include <qapplication.h> #include <qthread.h> #include <poll.h> #include <qevent.h> #include <linux/if.h> #include "network_ctrl_recv_thread.h" #include "network_audio_recv_thread.h" #include "network_video_recv_thread.h" #include "video_cap.h" #include "capture_event.h" #include "video_send.h" #include "network_audio_send.h" #include "network_video_send.h" #include "network_ctrl.h" #include "video.h" #include "network.h" #include "common.h" #include "audio.h" #include "avi.h" #include "signal_def.h" #include "capture_event.h" using namespace std; /////////////////////////////////////////////////////// // Public Functions /////////////////////////////////////////////////////// // 构造函数 // 传入参数为 // nc_in 上层network_ctrl对象指针 // stackSize QThread所用的参数 network_ctrl_recv_thread::network_ctrl_recv_thread ( avi * avi_ptr_in, network_ctrl * nc_in, unsigned int stackSize ) :QThread( stackSize ) // {{{ { verbose_output( 2, "create network_ctrl_recv_thread." ); nc = nc_in; fd_ctrl = 0; recv_buff = new BUFF [ PACKET_LENGTH ]; send_buff = new BUFF [ PACKET_LENGTH ]; addr_accept = new sockaddr_in; acclen = new socklen_t; packet_num = 0; expect_num = 0; nart = NULL; nvrt = NULL; avi_ptr = avi_ptr_in; } // }}} // 析构函数 network_ctrl_recv_thread::~network_ctrl_recv_thread ( void ) // {{{ { if ( 0 != fd_ctrl ) { close( fd_ctrl ); } if ( NULL != nart ) { if ( nart->running() ) { nart->terminate(); cerr << "Warning! Terminate network audio recv thread." << endl; } delete nart; } if ( NULL != nvrt ) { if ( nvrt->running() ) { nvrt->terminate(); cerr << "Warning! Terminate network video recv thread." << endl; } delete nvrt; } delete [] recv_buff; delete [] send_buff; delete addr_accept; delete acclen; } // }}} // 运行部分,线程代码在这里 void network_ctrl_recv_thread::run ( void ) // {{{ { verbose_output( 1, "network ctrl recv thread running..." ); int init_ok; if ( avi_ptr->use_multicast ) { init_ok = connect_init_mc(); } else { init_ok = connect_init(); } if ( init_ok == SUCCEED ) { if ( avi_ptr->va_mode != AUDIO_ONLY ) { verbose_output( 1, "create new network_video_recv_thread." ); nvrt = new network_video_recv_thread( avi_ptr, nc ); nvrt->start(); } if ( avi_ptr->va_mode != VIDEO_ONLY ) { verbose_output( 1, "create new network_audio_recv_thread." ); nart = new network_audio_recv_thread( avi_ptr, nc ); nart->start(); } if ( avi_ptr->use_multicast ) { connect_handle_mc(); } else { connect_handle(); } } verbose_output( 1, "end of network_audio_recv_thread" ); return; } // }}} /////////////////////////////////////////////////////// // Private Functions /////////////////////////////////////////////////////// // 连接初始化,创建套接字 int network_ctrl_recv_thread::connect_init ( void ) // {{{ { verbose_output( 3, "network_ctrl_recv_thread init." ); //expect_num = WELCOME_NUM; *acclen = sizeof( *addr_accept ); memset( addr_accept, 0, *acclen ); // 网络连接的参数设置 addr_accept->sin_family = AF_INET; addr_accept->sin_port = htons( DEFAULT_CTRL_PORT ); inet_pton( AF_INET, static_cast< const char* > ( avi_ptr->ip ), &addr_accept->sin_addr ); verbose_output( 3, "creating ctrl connect socket..." ); fd_ctrl = socket( AF_INET, SOCK_DGRAM, 0 ); pollfd connect_to = { fd_ctrl, POLLIN, 0, }; bool read_ok = false; option_t * opt_buf = NULL; BUFF * temp; int connect_times = 0; bool should_exit = false; packet_head_t * packet_head = NULL; do { (*(nc->term_sub_thread_sema))++; should_exit = nc->term_sub_thread; (*(nc->term_sub_thread_sema))--; if ( should_exit ) { QCustomEvent * event = new QCustomEvent( SIG_DISCONNECT_OK ); QApplication::postEvent( avi_ptr, event ); return FAILED; } verbose_output( 3, "send ctrl Hello message ..." ); send_data( fd_ctrl, addr_accept, send_buff, NULL, 0, expect_num, SYN ); int result = poll( &connect_to, 1, DEFAULT_TIMEOUT ); if ( result == 0 ) { // 超时返回 connect_times++; if ( connect_times >= DEFAULT_CONNECT_TIMES ) { cerr << "Warning! Can't connect to peer host." << endl; QCustomEvent * event = new QCustomEvent( SIG_CONNECT_TIMEOUT ); QApplication::postEvent( avi_ptr, event ); return FAILED; } continue; } else { if ( result > 0 ) { // 网络可读 recv_line( fd_ctrl, addr_accept, recv_buff, temp, packet_head ); opt_buf = (option_t *) temp; if ( !TEST_CTRL_SYN_BIT( packet_head->opt_bits ) ) { cerr << "Warning! not the Welcome reply." << endl; } else { read_ok = true; } } else { // 套接口错误 perror( "Error in connecting" ); ::exit( 1 ); } } } while ( !read_ok ); expect_num++; QCustomEvent * event = new QCustomEvent( SIG_CONNECT_OK ); QApplication::postEvent( avi_ptr, (QEvent*) event ); // 获得参数设置 avi_ptr->va_mode = opt_buf->va_mode; avi_ptr->video_opt.factor = opt_buf->factor; if ( opt_buf->use_g723 == 0 ) { avi_ptr->use_g723 = false; } else { if ( opt_buf->use_g723 == 1 ) { avi_ptr->use_g723 = true; } } verbose_output( 4, "get peer configuration" ); verbose_output( 4, "va_mode\t", avi_ptr->va_mode ); verbose_output( 4, "factor\t", avi_ptr->video_opt.factor ); verbose_output( 4, "use_g723\t", opt_buf->use_g723 ); return SUCCEED; } // }}} // 处理连接后的数据发送工作 void network_ctrl_recv_thread::connect_handle ( void ) // {{{ { bool should_exit = false; int count = 0; while( 1 ) { (*(nc->term_sub_thread_sema))++; should_exit = nc->term_sub_thread; (*(nc->term_sub_thread_sema))--; if ( should_exit ) { send_data( fd_ctrl, addr_accept, send_buff, NULL, 0, packet_num, GOODBYE ); QCustomEvent * event = new QCustomEvent( SIG_DISCONNECT_OK ); QApplication::postEvent( avi_ptr, event ); nart->wait(); cout << " wait nart ok " << endl; nvrt->wait(); cout << " wait nvrt ok " << endl; return; } msleep( HEARTBEAT_INTERVAL / 4 ); count = ( count + 1 ) % 4; if ( count == 3 ) { cout << "send heartbeat" << endl; send_data( fd_ctrl, addr_accept, send_buff, NULL, 0, packet_num, HEARTBEAT ); } } return; } // }}} // 组播初始化,创建套接字 int network_ctrl_recv_thread::connect_init_mc ( void ) // {{{ { verbose_output( 3, "network ctrl recv thread Multicast init." ); ///////////////////////////////////////// // 创建控制端口 ///////////////////////////////////////// *acclen = sizeof( *addr_accept ); memset( addr_accept, 0, *acclen ); // 创建控制端监听socket verbose_output( 3, "creating multicast listen socket..." ); fd_ctrl = socket( AF_INET, SOCK_DGRAM, 0 ); // 绑定指定端口 addr_accept->sin_family = AF_INET; inet_pton( AF_INET, static_cast< const char* >( avi_ptr->mc_addr ), &addr_accept->sin_addr ); addr_accept->sin_port = htons( DEFAULT_MC_CTRL_PORT ); // 绑定端口 if ( bind( fd_ctrl, (sockaddr*) addr_accept, *acclen ) == -1 ) { cerr << "Can't bind to the listen port [" << DEFAULT_MC_CTRL_PORT << "]" << endl; ::exit( 1 ); } // 初始化组播 ip_mreq mreq; memcpy( &mreq.imr_multiaddr, &(((sockaddr_in*) addr_accept)->sin_addr), sizeof( in_addr ) ); mreq.imr_interface.s_addr = htonl( INADDR_ANY ); // 加入组播组 setsockopt( fd_ctrl, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof( mreq ) ); return SUCCEED; } // }}} // 处理组播连接后的数据接收工作 void network_ctrl_recv_thread::connect_handle_mc ( void ) // {{{ { nart->wait(); cout << " wait nart ok " << endl; nvrt->wait(); cout << " wait nvrt ok " << endl; QCustomEvent * event = new QCustomEvent( SIG_DISCONNECT_OK ); QApplication::postEvent( avi_ptr, event ); return; } // }}}