int CRtmpdSession::Init( sqbind::CSqSocket *pSocket ) { oexAutoLock ll( _g_rtmpd_lock ); if ( !ll.IsLocked() ) return 0; // Out with the old Destroy(); #if _DEBUG // Unfortunately, this is a must for the debug version if ( !netstackdump || !netstackdump_read ) { setLastErrorStr( "You must call StartDebugLog() in debug versions" ); return 0; } // end if #endif // Sanity check if ( !pSocket || !pSocket->Ptr() ) { setLastErrorStr( "Invalid socket" ); return 0; } // end if // Initialize the session object RTMP_Init( &m_session ); // Mark stream as live // m_session.Link.lFlags |= RTMP_LF_LIVE; // Set short timeout // m_session.Link.timeout = 15; // Give the rtmpd object control of the socket handle m_session.m_sb.sb_socket = oexPtrToInt( pSocket->Ptr()->Detach() ); // Disable Nagle's algorithm int on = 1; setsockopt( m_session.m_sb.sb_socket, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof( on ) ); // Attempt handshake if ( !RTMP_Serve( &m_session ) ) { setLastErrorStr( "RTMP handshake failed" ); return 0; } // end if return 1; }
int RtmpSessionHandshake(RTMP_SESSION *pSession) { int iRet = 0; RTMPPacket *packet = (RTMPPacket *)malloc(sizeof(RTMPPacket)); if(NULL == packet) { return ERROR_FAILED; } RTMPPacket_Init(packet); pSession->pPkt = packet; RTMP *rtmp = RTMP_Alloc(); if(NULL == rtmp ) { return ERROR_FAILED; } RTMP_Init(rtmp); rtmp->m_sb.sb_socket = pSession->socket; pSession->prtmp = rtmp; pSession->state = RTMPSERVER_STATE_INIT; /* 进行握手处理 */ if(RTMP_Serve(rtmp)) { RTMPPacket_Free(pSession->pPkt); RTMPPacket_Init(pSession->pPkt); pSession->handshake = 1; pSession->arglen = 0; SetNonBlocking(pSession->socket); } else { iRet = -1; } return iRet; }
void doServe(STREAMING_SERVER * server, // server socket and state (our listening socket) int sockfd // client connection socket ) { server->state = STREAMING_IN_PROGRESS; RTMP rtmp = { 0 }; /* our session with the real client */ RTMPPacket packet = { 0 }; // timeout for http requests fd_set fds; struct timeval tv; memset(&tv, 0, sizeof(struct timeval)); tv.tv_sec = 5; FD_ZERO(&fds); FD_SET(sockfd, &fds); if (select(sockfd + 1, &fds, NULL, NULL, &tv) <= 0) { RTMP_Log(RTMP_LOGERROR, "Request timeout/select failed, ignoring request"); goto quit; } else { RTMP_Init(&rtmp); rtmp.m_sb.sb_socket = sockfd; if (!RTMP_Serve(&rtmp)) { RTMP_Log(RTMP_LOGERROR, "Handshake failed"); goto cleanup; } } server->arglen = 0; while (RTMP_IsConnected(&rtmp) && RTMP_ReadPacket(&rtmp, &packet)) { if (!RTMPPacket_IsReady(&packet)) continue; ServePacket(server, &rtmp, &packet); RTMPPacket_Free(&packet); } cleanup: RTMP_LogPrintf("Closing connection... "); RTMP_Close(&rtmp); /* Should probably be done by RTMP_Close() ... */ rtmp.Link.playpath.av_val = NULL; rtmp.Link.tcUrl.av_val = NULL; rtmp.Link.swfUrl.av_val = NULL; rtmp.Link.pageUrl.av_val = NULL; rtmp.Link.app.av_val = NULL; rtmp.Link.flashVer.av_val = NULL; RTMP_LogPrintf("done!\n\n"); quit: if (server->state == STREAMING_IN_PROGRESS) server->state = STREAMING_ACCEPTING; return; }