int zmq::gssapi_client_t::next_handshake_command (msg_t *msg_) { if (state == send_ready) { int rc = produce_ready(msg_); if (rc == 0) state = connected; return rc; } if (state != call_next_init) { errno = EAGAIN; return -1; } if (initialize_context () < 0) return -1; if (produce_next_token (msg_) < 0) return -1; if (maj_stat != GSS_S_CONTINUE_NEEDED && maj_stat != GSS_S_COMPLETE) return -1; if (maj_stat == GSS_S_COMPLETE) { security_context_established = true; state = recv_ready; } else state = recv_next_token; return 0; }
struct shttpd_ctx * shttpd_init(const char *config_file, ...) { struct shttpd_ctx *ctx; va_list ap; const char *opt_name, *opt_value; char *tmpvars[NELEMS(options)]; const struct opt *opt; size_t i; /* Initialize all temporary holders to NULL */ for (i = 0; i < NELEMS(tmpvars); i++) tmpvars[i] = NULL; if ((ctx = malloc(sizeof(*ctx))) != NULL) { va_start(ap, config_file); while ((opt_name = va_arg(ap, const char *)) != NULL) { opt_value = va_arg(ap, const char *); if ((opt = find_option(0, opt_name)) == NULL) elog(E_FATAL, NULL, "shttpd_init: " "unknown variable [%s]", opt_name); set_option(opt, opt_value, tmpvars); } va_end(ap); initialize_context(ctx, config_file, 0, NULL, tmpvars); }
/* Fonction d'initialisation SVN / APR */ void svn_init(){ if (svn_cmdline_init ("svn_support", stderr) != EXIT_SUCCESS) return; pool = svn_pool_create(NULL); ctx = initialize_context(); /*err = svn_fs_initialize(pool); if (err) { svn_handle_error2 (err, stderr, FALSE, "svn_init: "); return; }*/ }
int main(int argc, char *argv[]) { AVFormatContext *ctx; int videoIdx, audioIdx, temp, i; double audioRate, videoRate; struct frame *myFrame = malloc(sizeof(struct frame)); initialize_context(&ctx, argv[1], &videoIdx, &audioIdx, &videoRate, &audioRate); printf("%i video: frame rate %f fps\n", videoIdx, videoRate); printf("%i audio: sample rate %f\n", audioIdx, audioRate); int vid, aud, a; vid = aud = a = 0; //while ( (temp = get_frame(ctx, myFrame, videoIdx, audioIdx, videoRate, audioRate)) >= 0) { for (i=0; i<100; i++) { temp = get_frame(ctx, myFrame, videoIdx, audioIdx, videoRate, audioRate); if (temp == videoIdx) { // tittidii //printf("Video %i, timestamp %i, size %i\n", vid, myFrame->timestamp, myFrame->size); vid++; } else if (temp == audioIdx) { // tattadaa printf("Audio %i, timestamp %i, size %i\n", aud, myFrame->timestamp, myFrame->size); uint8_t *data = myFrame->data; printf("data: "); for (a=0; a<myFrame->size; a++) { printf("%i:", *data); data++; } printf("\n"); aud++; } } close_context(ctx); return 0; }
struct shttpd_ctx * init_from_argc_argv(const char *config_file, int argc, char *argv[]) { struct shttpd_ctx *ctx; // NELEMS 是(sizeof(ar) / sizeof(ar[0])) 一个宏来着 // options是一个结构体数组 //tmpvars是一个指针数组来着 char *tmpvars[NELEMS(options)]; size_t i; /* Initialize all temporary holders to NULL */ for (i = 0; i < NELEMS(tmpvars); i++) tmpvars[i] = NULL; //当前的shttpd的核心数据结构环境变量空间分配 if ((ctx = malloc(sizeof(*ctx))) != NULL) initialize_context(ctx, config_file, argc, argv, tmpvars); return (ctx); }
void SaxParser::finish_chunk_parsing() { xmlResetLastError(); if(!context_) { context_ = xmlCreatePushParserCtxt( sax_handler_.get(), 0, // this, // user_data 0, // chunk 0, // size 0); // no filename for fetching external entities if(!context_) { throw internal_error("Could not create parser context\n" + format_xml_error()); } initialize_context(); } else xmlCtxtResetLastError(context_); int parseError = XML_ERR_OK; if(!exception_) //This is called just to terminate parsing. parseError = xmlParseChunk(context_, 0 /* chunk */, 0 /* size */, 1 /* terminate (1 or 0) */); Glib::ustring error_str = format_xml_parser_error(context_); if (error_str.empty() && parseError != XML_ERR_OK) error_str = "Error code from xmlParseChunk(): " + Glib::ustring::format(parseError); release_underlying(); // Free context_ check_for_exception(); if(!error_str.empty()) { throw parse_error(error_str); } }
// implementation of this function is inspired by the SAX documentation by James Henstridge. // (http://www.daa.com.au/~james/gnome/xml-sax/implementing.html) void SaxParser::parse() { //TODO If this is not the first parsing with this SaxParser, the xmlDoc object // in entity_resolver_doc_ should be deleted and replaced by a new one. // Otherwise entity declarations from a previous parsing may erroneously affect // this parsing. This would be much easier if entity_resolver_doc_ were a // std::auto_ptr<Document>, so the xmlpp::Document could be deleted and a new // one created. A good place for such code would be in an overridden // SaxParser::initialize_context(). It would be an ABI break. if(!context_) { throw internal_error("Parser context not created."); } xmlSAXHandlerPtr old_sax = context_->sax; context_->sax = sax_handler_.get(); xmlResetLastError(); initialize_context(); const int parseError = xmlParseDocument(context_); context_->sax = old_sax; Glib::ustring error_str = format_xml_parser_error(context_); if (error_str.empty() && parseError == -1) error_str = "xmlParseDocument() failed."; release_underlying(); // Free context_ check_for_exception(); if(!error_str.empty()) { throw parse_error(error_str); } }
void SaxParser::parse_chunk_raw(const unsigned char* contents, size_type bytes_count) { KeepBlanks k(KeepBlanks::Default); xmlResetLastError(); if(!context_) { context_ = xmlCreatePushParserCtxt( sax_handler_.get(), 0, // user_data 0, // chunk 0, // size 0); // no filename for fetching external entities if(!context_) { throw internal_error("Could not create parser context\n" + format_xml_error()); } initialize_context(); } else xmlCtxtResetLastError(context_); int parseError = XML_ERR_OK; if(!exception_) parseError = xmlParseChunk(context_, (const char*)contents, bytes_count, 0 /* don't terminate */); check_for_exception(); Glib::ustring error_str = format_xml_parser_error(context_); if (error_str.empty() && parseError != XML_ERR_OK) error_str = "Error code from xmlParseChunk(): " + Glib::ustring::format(parseError); if(!error_str.empty()) { throw parse_error(error_str); } }
int RDMAServer::start_server (int server_num) { tcp_port = TCP_PORT[server_num]; ib_port = IB_PORT[server_num]; RDMAServerContext ctx[CLIENTS_CNT]; char temp_char; TEST_NZ(initialize_data_structures()); std::cout << "[Info] Server " << server_num << " is waiting for " << CLIENTS_CNT << " client(s) on tcp port: " << tcp_port << ", ib port: " << ib_port << std::endl; server_sockfd = -1; struct sockaddr_in serv_addr, cli_addr; socklen_t clilen = sizeof(cli_addr); pthread_t master_threads[CLIENTS_CNT]; // Open Socket server_sockfd = socket (AF_INET, SOCK_STREAM, 0); if (server_sockfd < 0) { std::cerr << "Error opening socket" << std::endl; return -1; } // Bind memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(tcp_port); TEST_NZ(bind(server_sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))); // listen TEST_NZ(listen (server_sockfd, CLIENTS_CNT)); // accept connections for (int i = 0; i < CLIENTS_CNT; i++){ initialize_context(ctx[i]); ctx[i].sockfd = accept (server_sockfd, (struct sockaddr *) &cli_addr, &clilen); if (ctx[i].sockfd < 0){ std::cerr << "ERROR on accept" << std::endl; return -1; } std::cout << "[Conn] Received client #" << i << " on socket " << ctx[i].sockfd << std::endl; // pthread_create(&master_threads[i], NULL, RDMAServer::handle_client, &client_socks[i]); // create all resources TEST_NZ (ctx[i].create_context()); DEBUG_COUT("[Info] Context for client " << i << " created"); // connect the QPs TEST_NZ (RDMACommon::connect_qp (&(ctx[i].qp), ctx[i].ib_port, ctx[i].port_attr.lid, ctx[i].sockfd)); DEBUG_COUT("[Conn] QPed to client " << i); // prepare server buffer with read message memcpy(&(ctx[i].send_msg.mr_items), ctx[i].mr_items, sizeof(struct ibv_mr)); memcpy(&(ctx[i].send_msg.mr_orders), ctx[i].mr_orders, sizeof(struct ibv_mr)); memcpy(&(ctx[i].send_msg.mr_order_line),ctx[i].mr_order_line, sizeof(struct ibv_mr)); memcpy(&(ctx[i].send_msg.mr_cc_xacts), ctx[i].mr_cc_xacts, sizeof(struct ibv_mr)); memcpy(&(ctx[i].send_msg.mr_timestamp), ctx[i].mr_timestamp, sizeof(struct ibv_mr)); memcpy(&(ctx[i].send_msg.mr_lock_items),ctx[i].mr_lock_items, sizeof(struct ibv_mr)); } for (int i = 0; i < CLIENTS_CNT; i++){ // send memory locations using SEND TEST_NZ (RDMACommon::post_SEND (ctx[i].qp, ctx[i].send_mr, (uintptr_t)&ctx[i].send_msg, sizeof(struct MemoryKeys), true)); TEST_NZ (RDMACommon::poll_completion(ctx[i].cq)); DEBUG_COUT("[Sent] buffer info to client " << i); } /* Server waits for the client to muck with its memory */ for (int i = 0; i < CLIENTS_CNT; i++) { TEST_NZ (sock_sync_data (ctx[i].sockfd, 1, "W", &temp_char)); /* just send a dummy char back and forth */ DEBUG_COUT("[Conn] Client " << i << " notified it's finished"); TEST_NZ (ctx[i].destroy_context()); std::cout << "[Info] Destroying client " << i << " resources" << std::endl; } std::cout << "[Info] Server's ready to gracefully get destroyed" << std::endl; }
int DQClientCentricServer::start_server () { tcp_port = SERVER_TCP_PORT; ib_port = SERVER_IB_PORT; DQServerContext ctx[CLIENTS_CNT]; struct sockaddr_in serv_addr, cli_addr; socklen_t clilen = sizeof(cli_addr); char temp_char; std::string clients_addresses; // separated by the delimiter '|' std::string clients_tcp_port; // separated by the delimiter '|' TEST_NZ(initialize_data_structures()); std::cout << "[Info] Server is waiting for " << CLIENTS_CNT << " client(s) on tcp port: " << tcp_port << ", ib port: " << ib_port << std::endl; // Open Socket server_sockfd = socket (AF_INET, SOCK_STREAM, 0); if (server_sockfd < 0) { std::cerr << "Error opening socket" << std::endl; return -1; } // Bind memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(tcp_port); TEST_NZ(bind(server_sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))); // listen TEST_NZ(listen (server_sockfd, CLIENTS_CNT)); // accept connections for (int i = 0; i < CLIENTS_CNT; i++){ initialize_context(ctx[i]); ctx[i].sockfd = accept (server_sockfd, (struct sockaddr *) &cli_addr, &clilen); if (ctx[i].sockfd < 0){ std::cerr << "ERROR on accept" << std::endl; return -1; } std::cout << "[Conn] Received client #" << i << " on socket " << ctx[i].sockfd << std::endl; ctx[i].client_ip = ""; ctx[i].client_ip += std::string(inet_ntoa (cli_addr.sin_addr)); clients_addresses.append(ctx[i].client_ip); clients_tcp_port.append(std::to_string(8000 + i)); // if the client is not the last client, add the delimiter if (i != CLIENTS_CNT - 1){ clients_addresses.append("|"); clients_tcp_port.append("|"); } // create all resources TEST_NZ (ctx[i].create_context()); DEBUG_COUT("[Info] Context for client " << i << " (" << ctx[i].client_ip << ") created"); // connect the QPs TEST_NZ (RDMACommon::connect_qp (&(ctx[i].qp), ctx[i].ib_port, ctx[i].port_attr.lid, ctx[i].sockfd)); DEBUG_COUT("[Conn] QPed to client " << i); } for (int i = 0; i < CLIENTS_CNT; i++){ // send memory locations using SEND memcpy(&(ctx[i].send_message_msg.peer_mr), ctx[i].locks_mr, sizeof(struct ibv_mr)); ctx[i].send_message_msg.client_id = static_cast<uint32_t>(i + 1); strcpy(ctx[i].send_message_msg.clients_addr, clients_addresses.c_str()); strcpy(ctx[i].send_message_msg.clients_tcp_port, clients_tcp_port.c_str()); DEBUG_COUT("[Sent] Cheeck: " << ctx[i].send_message_msg.clients_addr); TEST_NZ (RDMACommon::post_SEND (ctx[i].qp, ctx[i].send_message_mr, (uintptr_t)&ctx[i].send_message_msg, sizeof (struct MemoryKeys), true)); TEST_NZ (RDMACommon::poll_completion(ctx[i].cq)); DEBUG_COUT("[Sent] buffer info to client " << i); } // Server waits for the client to muck with its memory /*************** THIS IS FOR SEND // accept connections for (int i = 0; i < CLIENTS_CNT; i++){ initialize_context(ctx[i]); ctx[i].sockfd = accept (server_sockfd, (struct sockaddr *) &cli_addr, &clilen); if (ctx[i].sockfd < 0){ std::cerr << "ERROR on accept" << std::endl; return -1; } std::cout << "[Conn] Received client #" << i << " on socket " << ctx[i].sockfd << std::endl; // create all resources TEST_NZ (ctx[i].create_context()); DEBUG_COUT("[Info] Context for client " << i << " created"); // connect the QPs TEST_NZ (RDMACommon::connect_qp (&(ctx[i].qp), ctx[i].ib_port, ctx[i].port_attr.lid, ctx[i].sockfd)); DEBUG_COUT("[Conn] QPed to client " << i); pthread_create(&master_threads[i], NULL, BenchmarkServer::handle_client, &ctx[i]); } std::cout << "[Info] Established connection to all " << CLIENTS_CNT << " client(s)." << std::endl; //wait for handlers to finish for (int i = 0; i < CLIENTS_CNT; i++) { pthread_join(master_threads[i], NULL); } */ for (int i = 0; i < CLIENTS_CNT; i++) { TEST_NZ (sock_sync_data (ctx[i].sockfd, 1, "W", &temp_char)); // just send a dummy char back and forth DEBUG_COUT("[Conn] Client " << i << " notified it's finished"); TEST_NZ (ctx[i].destroy_context()); std::cout << "[Info] Destroying client " << i << " resources" << std::endl; } std::cout << "[Info] Server's ready to gracefully get destroyed" << std::endl; }
int main(int argc, char *argv[]) { if (initialize_context(&my_context, argc, argv) != 0) { usage(argv[0]); return 1; } if (art_tree_map_init(&myds, &my_context) != 0) { fprintf(stderr, "failed to initialize memory pool file\n"); return 1; } if (my_context.pop == NULL) { perror("pool initialization"); return 1; } if (art_tree_init(my_context.pop, &my_context.newpool)) { perror("pool setup"); return 1; } if ((my_context.mode & FILL)) { if (add_elements(&my_context)) { perror("add elements"); return 1; } } if ((my_context.mode & INSERT)) { if (insert_element(&my_context)) { perror("insert elements"); return 1; } } if ((my_context.mode & SEARCH)) { if (search_element(&my_context)) { perror("search elements"); return 1; } } if ((my_context.mode & REMOVE)) { if (delete_element(&my_context)) { perror("delete elements"); return 1; } } if (my_context.mode & DUMP) { art_iter(my_context.pop, dump_art_leaf_callback, NULL); } if (my_context.mode & GRAPH) { printf("digraph g {\nrankdir=LR;\n"); art_iter(my_context.pop, dump_art_node_callback, NULL); printf("}"); } exit_handler(&my_context); return 0; }
void SaxParser::parse_stream(std::istream& in) { if(context_) { throw parse_error("Attempt to start a second parse while a parse is in progress."); } KeepBlanks k(KeepBlanks::Default); xmlResetLastError(); context_ = xmlCreatePushParserCtxt( sax_handler_.get(), 0, // user_data 0, // chunk 0, // size 0); // no filename for fetching external entities if(!context_) { throw internal_error("Could not create parser context\n" + format_xml_error()); } initialize_context(); //TODO: Shouldn't we use a Glib::ustring here, and some alternative to std::getline()? int firstParseError = XML_ERR_OK; std::string line; while( ( ! exception_ ) && std::getline(in, line)) { // since getline does not get the line separator, we have to add it since the parser care // about layout in certain cases. line += '\n'; const int parseError = xmlParseChunk(context_, line.c_str(), line.size() /* This is a std::string, not a ustring, so this is the number of bytes. */, 0 /* don't terminate */); // Save the first error code if any, but read on. // More errors might be reported and then thrown by check_for_exception(). if (parseError != XML_ERR_OK && firstParseError == XML_ERR_OK) firstParseError = parseError; } if( ! exception_ ) { //This is called just to terminate parsing. const int parseError = xmlParseChunk(context_, 0 /* chunk */, 0 /* size */, 1 /* terminate (1 or 0) */); if (parseError != XML_ERR_OK && firstParseError == XML_ERR_OK) firstParseError = parseError; } Glib::ustring error_str = format_xml_parser_error(context_); if (error_str.empty() && firstParseError != XML_ERR_OK) error_str = "Error code from xmlParseChunk(): " + Glib::ustring::format(firstParseError); release_underlying(); // Free context_ check_for_exception(); if(!error_str.empty()) { throw parse_error(error_str); } }
int start_server(const char *url, const char *rtspport) { int mediafd = -1, listenfd, tempfd, maxfd; int videofd; struct addrinfo *info; struct sockaddr_storage remoteaddr; socklen_t addrlen = sizeof remoteaddr; fd_set readfds, masterfds; struct timeval *timeout, *timeind = NULL, timenow; int nready, i; int videosize, videoleft; int recvd, sent; char urlhost[URLSIZE], urlpath[URLSIZE], tempstr[URLSIZE]; unsigned char msgbuf[BUFSIZE], sendbuf[BUFSIZE]; char *temp; unsigned char *sps = NULL, *pps = NULL; size_t spslen, ppslen; RTSPMsg rtspmsg; Client streamclient; pthread_t threadid; ThreadInfo *tinfo = NULL; uint16_t rtpseqno_video = (rand() % 1000000); uint16_t rtpseqno_audio = (rand() % 1000000); TimeoutEvent *event; /* The current state of the protocol */ int mediastate = IDLE; int quit = 0; int media_downloaded = 0; timeout = (struct timeval *)malloc(sizeof(struct timeval)); init_client(&streamclient); /* Open the a file where the video is to be stored */ if ((videofd = open("videotemp.mp4", O_RDWR | O_CREAT | O_TRUNC, S_IRWXU)) < 0) { fatal_error("Error opening the temporary videofile"); } /* Create the RTSP listening socket */ resolve_host(NULL, rtspport, SOCK_STREAM, AI_PASSIVE, &info); listenfd = server_socket(info); maxfd = listenfd; FD_ZERO(&readfds); FD_ZERO(&masterfds); FD_SET(listenfd, &masterfds); while (!quit) { readfds = masterfds; if ((nready = Select(maxfd + 1, &readfds, timeind)) == -1) { printf("Select interrupted by a signal\n"); } /* Timeout handling, used for packet pacing and other timeouts */ else if (nready == 0) { timeind = NULL; lock_mutex(&queuelock); if ((event = pull_event(&queue)) != NULL) { switch (event->type) { case ENDOFSTREAM: printf("MEDIA FINISHED\n"); break; case FRAME: /* Video frame */ if (event->frame->frametype == VIDEO_FRAME) { rtpseqno_video += send_video_frame(sendbuf, event->frame, streamclient.videofds[0], rtpseqno_video); } /* Audio frame */ else { rtpseqno_audio += send_audio_frame(sendbuf, event->frame, streamclient.audiofds[0], rtpseqno_audio); } free(event->frame->data); free(event->frame); break; case CHECKMEDIASTATE: oma_debug_print("Checking media ready for streaming...\n"); if (mediastate != STREAM) { printf("Sending dummy RTP\n"); send_dummy_rtp(sendbuf, streamclient.videofds[0], &rtpseqno_video); push_timeout(&queue, 1000, CHECKMEDIASTATE); } break; default: oma_debug_print("ERRORENOUS EVENT TYPE!\n"); break; } /* If there are elements left in the queue, calculate next timeout */ if (queue.size > 0) { *timeout = calculate_delta(&event->time, &queue.first->time); timeind = timeout; oma_debug_print("Timeout: %ld secs, %ld usecs\n", timeout->tv_sec, timeout->tv_usec); } else { oma_debug_print("The first entry of the queue is NULL!\n"); } if (queue.size < QUEUESIZE / 2) { oma_debug_print("Signaling thread to start filling the queue"); pthread_cond_signal(&queuecond); } free(event); } unlock_mutex(&queuelock); continue; } /* End of timeout handling */ /* Start to loop through the file descriptors */ for (i = 0; i <= maxfd; i++) { if (FD_ISSET(i, &readfds)) { nready--; /* New connection from a client */ if (i == listenfd) { oma_debug_print("Recieved a new RTSP connection\n"); fflush(stdout); if ((tempfd = accept(i, (struct sockaddr *)&remoteaddr, &addrlen)) == -1) { if (errno != EWOULDBLOCK && errno != ECONNABORTED && errno != EPROTO && errno != EINTR) { fatal_error("accept"); } } /* If we are already serving a client, close the new connection. Otherwise, continue. */ if (streamclient.state != NOCLIENT) { printf("Another RTSP client tried to connect. Sorry, we can only serve one client at a time\n"); close (tempfd); } else { streamclient.rtspfd = tempfd; streamclient.state = CLICONNECTED; maxfd = max(2, streamclient.rtspfd, maxfd); FD_SET(streamclient.rtspfd, &masterfds); } } /* Data from the media source */ else if (i == mediafd) { switch (mediastate) { case GETSENT: /* Read ONLY the HTTP message from the socket and store the video size */ recvd = recv_all(i, msgbuf, BUFSIZE, MSG_PEEK); temp = strstr((char *)msgbuf, "\r\n\r\n"); recvd = recv_all(i, msgbuf, (int)(temp + 4 - (char *)msgbuf), 0); printf("Received HTTP response\n%s\n", msgbuf); temp = strstr((char *)msgbuf, "Content-Length:"); sscanf(temp, "Content-Length: %d", &videosize); videoleft = videosize; mediastate = RECVTCP; break; case RECVTCP: if ((recvd = recv_all(i, msgbuf, BUFSIZE, 0)) == 0) { FD_CLR(i, &masterfds); close(i); oma_debug_print("Socket closed\n"); } oma_debug_print("Received data from video source!\n"); writestr(videofd, msgbuf, recvd); videoleft -= recvd; if (videoleft <= 0) { printf("Video download complete.\n"); FD_CLR(mediafd, &masterfds); close(videofd); close(mediafd); media_downloaded = 1; printf("Media socket closed\n"); /* Create the context and the queue filler thread parameter struct */ tinfo = (ThreadInfo *)malloc(sizeof(ThreadInfo)); initialize_context(&tinfo->ctx, "videotemp.mp4", &tinfo->videoIdx, &tinfo->audioIdx, &tinfo->videoRate, &tinfo->audioRate, &sps, &spslen, &pps, &ppslen); /* Launch the queue filler thread */ CHECK((pthread_create(&threadid, NULL, fill_queue, tinfo)) == 0); pthread_detach(threadid); /* Send the sprop-parameters before any other frames */ send_video_frame(sendbuf, create_sprop_frame(sps, spslen, 0), streamclient.videofds[0], rtpseqno_video++); send_video_frame(sendbuf, create_sprop_frame(pps, ppslen, 0), streamclient.videofds[0], rtpseqno_video++); g_free(sps); g_free(pps); lock_mutex(&queuelock); push_timeout(&queue, 1000, CHECKMEDIASTATE); unlock_mutex(&queuelock); mediastate = STREAM; } break; case STREAM: /* close(videofd); close(mediafd); close(listenfd); quit = 1; */ break; default: break; } } /* Data from a client ( i == streamclient.rtspfd) */ else { oma_debug_print("Received data from rtspfd\n"); fflush(stdout); if ((recvd = recv_all(i, msgbuf, BUFSIZE, 0)) == 0) { FD_CLR(i, &masterfds); close(i); oma_debug_print("RTSP client closed the connection\n"); streamclient.state = NOCLIENT; } else { oma_debug_print("%s", msgbuf); parse_rtsp(&rtspmsg, msgbuf); } if (rtspmsg.type == TEARDOWN) { /* Kill thread and empty queue */ lock_mutex(&queuelock); pthread_cancel(threadid); empty_queue(&queue); sleep(1); /* Reply with 200 OK */ sent = rtsp_teardown(&rtspmsg, sendbuf); send_all(i, sendbuf, sent); FD_CLR(i, &masterfds); close(i); close(streamclient.videofds[0]); close(streamclient.videofds[1]); close(streamclient.audiofds[0]); close(streamclient.audiofds[1]); printf("Closing AVFormatContext\n"); close_context(tinfo->ctx); free(tinfo); rtpseqno_video = (rand() % 1000000) + 7; rtpseqno_audio = rtpseqno_video + 9; init_client(&streamclient); printf("Closing RTSP client sockets (RTP&RTCP)\n"); streamclient.state = NOCLIENT; unlock_mutex(&queuelock); pthread_cond_signal(&queuecond); } switch (streamclient.state) { case CLICONNECTED: if (rtspmsg.type == OPTIONS) { sent = rtsp_options(&rtspmsg, &streamclient, sendbuf); send_all(i, sendbuf, sent); } else if (rtspmsg.type == DESCRIBE) { if (media_downloaded == 0) { /* Start fetching the file from the server */ parse_url(url, urlhost, urlpath); resolve_host(urlhost, "80", SOCK_STREAM, 0, &info); mediafd = client_socket(info, 0); FD_SET(mediafd, &masterfds); maxfd = max(2, maxfd, mediafd); /* Send the GET message */ http_get(url, msgbuf); send_all(mediafd, msgbuf, strlen((char *)msgbuf)); mediastate = GETSENT; } else { mediastate = STREAM; } /* Send the SDP without sprop-parameter-sets, those are sent * later in-band */ streamclient.state = SDPSENT; sent = rtsp_describe(&streamclient, sendbuf); send_all(i, sendbuf, sent); } break; case SDPSENT: if (rtspmsg.type == SETUP) { streamclient.setupsreceived++; /* Open up the needed ports and bind them locally. The RTCP ports opened here * are not really used by this application. */ write_remote_ip(tempstr, streamclient.rtspfd); oma_debug_print("Remote IP: %s\n", tempstr); if (streamclient.setupsreceived < 2) { resolve_host(tempstr, rtspmsg.clirtpport, SOCK_DGRAM, 0, &info); streamclient.audiofds[0] = client_socket(info, streamclient.server_rtp_audio_port); resolve_host(tempstr, rtspmsg.clirtcpport, SOCK_DGRAM, 0, &info); streamclient.audiofds[1] = client_socket(info, streamclient.server_rtcp_audio_port); sent = rtsp_setup(&rtspmsg, &streamclient, sendbuf, streamclient.server_rtp_audio_port, streamclient.server_rtcp_audio_port); } else { resolve_host(tempstr, rtspmsg.clirtpport, SOCK_DGRAM, 0, &info); streamclient.videofds[0] = client_socket(info, streamclient.server_rtp_video_port); resolve_host(tempstr, rtspmsg.clirtcpport, SOCK_DGRAM, 0, &info); streamclient.audiofds[1] = client_socket(info, streamclient.server_rtcp_video_port); sent = rtsp_setup(&rtspmsg, &streamclient, sendbuf, streamclient.server_rtp_video_port, streamclient.server_rtcp_video_port); streamclient.state = SETUPCOMPLETE; } oma_debug_print("Sending setup response...\n"); send_all(i, sendbuf, sent); } break; case SETUPCOMPLETE: if (rtspmsg.type == PLAY) { /* Respond to the PLAY request, and start sending dummy RTP packets * to disable the client timeout */ sent = rtsp_play(&rtspmsg, sendbuf); send_all(i, sendbuf, sent); if (media_downloaded == 0) { lock_mutex(&queuelock); push_timeout(&queue, 100, CHECKMEDIASTATE); unlock_mutex(&queuelock); } /* Media has already been once downloaded, initialize context and thread */ else { tinfo = (ThreadInfo *)malloc(sizeof(ThreadInfo)); initialize_context(&tinfo->ctx, "videotemp.mp4", &tinfo->videoIdx, &tinfo->audioIdx, &tinfo->videoRate, &tinfo->audioRate, &sps, &spslen, &pps, &ppslen); /* Launch the queue filler thread */ CHECK((pthread_create(&threadid, NULL, fill_queue, tinfo)) == 0); pthread_detach(threadid); /* Send the sprop-parameters before any other frames */ send_video_frame(sendbuf, create_sprop_frame(sps, spslen, 0), streamclient.videofds[0], rtpseqno_video++); send_video_frame(sendbuf, create_sprop_frame(pps, ppslen, 0), streamclient.videofds[0], rtpseqno_video++); g_free(sps); g_free(pps); /* Dummy timeouts to start queue/timeout mechanism */ push_timeout(&queue, 100, CHECKMEDIASTATE); push_timeout(&queue, 2000, CHECKMEDIASTATE); } } break; default: break; } } } if (nready <= 0) break; } /* Set the timeout value again, since select will mess it up */ lock_mutex(&queuelock); if (queue.size > 0) { CHECK((gettimeofday(&timenow, NULL)) == 0); *timeout = calculate_delta(&timenow, &queue.first->time); /* oma_debug_print("Delta sec: %ld, Delta usec: %ld\n", timeout->tv_sec, timeout->tv_usec); */ if (timeout->tv_sec < 0) { timeout->tv_sec = 0; timeout->tv_usec = 0; } timeind = timeout; } else timeind = NULL; unlock_mutex(&queuelock); } return 1; }