void test_socket(void) { int server_fd, client_fd, fd, pid, ret, val; struct sockaddr_in sockaddr; socklen_t len; char buf[512]; server_fd = server_socket(); /* test a few socket options */ len = sizeof(val); chk_error(getsockopt(server_fd, SOL_SOCKET, SO_TYPE, &val, &len)); if (val != SOCK_STREAM) error("getsockopt"); pid = chk_error(fork()); if (pid == 0) { client_fd = client_socket(); send(client_fd, socket_msg, sizeof(socket_msg), 0); close(client_fd); exit(0); } len = sizeof(sockaddr); fd = chk_error(accept(server_fd, (struct sockaddr *)&sockaddr, &len)); ret = chk_error(recv(fd, buf, sizeof(buf), 0)); if (ret != sizeof(socket_msg)) error("recv"); if (memcmp(buf, socket_msg, sizeof(socket_msg)) != 0) error("socket_msg"); chk_error(close(fd)); chk_error(close(server_fd)); }
void start_mc_server() { /* create the listening socket and bind it */ if (settings.socketpath == NULL) { l_socket = server_socket(settings.port, 0); if (l_socket == -1) { fprintf(stderr, "failed to listen\n"); exit(EXIT_FAILURE); } } /* initialize main thread libevent instance */ main_base = event_init(); /* create the initial listening connection */ /*if (!(listen_conn = conn_new(l_socket, conn_listening, EV_READ | EV_PERSIST, 1, false, main_base))) { fprintf(stderr, "failed to create listening connection"); exit(EXIT_FAILURE); }*/ struct event ev; event_set(&ev, l_socket, EV_READ | EV_PERSIST, event_handler, (void *)&l_socket); //函数创建新的事件结构 event_base_set(main_base, &ev); //event_add使通过event_set()设置的事件在事件匹配或超时时(如果设置了超时)被执行 if (event_add(&ev, 0) == -1) { //close(l_socket); } thread_init(settings.num_threads, main_base);/* llthread.c */ /* enter the event loop */ event_base_loop(main_base, 0); }
int try_open_new_listening_sockets (struct mc_config *MC) { int i, j, sfd; for (i = 0; i < MC->clusters_num; i++) { if (MC->Clusters[i].other_cluster_no >= 0) { continue; } sfd = server_socket (MC->Clusters[i].port, settings_addr, backlog, 0); if (sfd >= MAX_CONNECTIONS) { vkprintf (0, "cannot open server socket at port %d: too many open connections (fd=%d)\n", MC->Clusters[i].port, sfd); close (sfd); sfd = -1; } if (sfd < 0) { vkprintf (0, "cannot open server socket at port %d: %m\n", MC->Clusters[i].port); for (j = 0; j < i; j++) { if (MC->Clusters[j].other_cluster_no < 0) { sfd = MC->Clusters[j].server_socket; close (sfd); MC->Clusters[j].server_socket = -1; vkprintf (1, "closed newly-opened listening socket at %s:%d, fd=%d\n", conv_addr (settings_addr.s_addr, 0), MC->Clusters[j].port, sfd); } } return -2; } vkprintf (1, "created listening socket at %s:%d, fd=%d\n", conv_addr (settings_addr.s_addr, 0), MC->Clusters[i].port, sfd); MC->Clusters[i].server_socket = sfd; } return 0; }
int main(int argc, char** argv){ /* 主线程主体流程: conn_init; thread_init; 还得有一个 stat_init stats的结构是用来记录当前的状态的,stats是一个静态变量 server_socket 请求,分发 注册事件loop */ int retval; main_base = event_init(); FILE *portnumber_file = NULL; portnumber_file = fopen("/tmp/portnumber.file", "a"); stats_init(); conn_init(); thread_init(NUM_OF_THREADS); server_socket("127.0.0.1", SERVER_PORT, tcp_transport, portnumber_file); if (event_base_loop(main_base, 0) != 0) { printf("event_base_loop error"); retval = EXIT_FAILURE; } return retval; exit(0); }
int main (int argc, char** argv) { pthread_t thread; int listener, nuevaConexion; /* Creación de archivo log */ Logger = log_create(LOG_PATH, "MSP", false, LOG_LEVEL_TRACE); clean_file(LOG_PATH); cargarConfiguracion(argv[1]); inicializarMSP(); log_trace(Logger, "Inicio de MSP.\n Tamaño de Memoria Principal: %u.\n Tamaño de SWAP: %u.", MaxMem, MaxSwap); listener = server_socket(Puerto); pthread_create(&thread, NULL, atenderConsola, NULL); while (true) { nuevaConexion = accept_connection(listener); pthread_mutex_lock(&LogMutex); log_trace(Logger, "Nueva conexión."); pthread_mutex_unlock(&LogMutex); pthread_create(&thread, NULL, atenderProceso, &nuevaConexion); } return EXIT_SUCCESS; }
int main(int argc, char *argv[]){ int soc; if(argc <= 1){ fprintf(stderr, "server port\n"); return(EX_USAGE); } if(argc >= 3 && argv[2][0] == 'n'){ fprintf(stderr, "Nonblocking mode\n"); g_mode = 'n'; } else { g_mode = 'b'; } if((soc = server_socket(argv[1])) == -1){ fprintf(stderr, "server_socket(%s):error\n", argv[1]); return(EX_UNAVAILABLE); } fprintf(stderr, "ready for accept\n"); accept_loop(soc); close(soc); return(EX_OK); }
Tunnel * tunnel_new_server (int port ) { Tunnel *tunnel; tunnel = ( Tunnel *) malloc (sizeof (Tunnel )); if ( tunnel == NULL ) return NULL ; //if ( content_length == 0 ) //content_length = DEFAULT_CONTENT_LENGTH; tunnel->in_fd = INVALID_SOCKET; tunnel->out_fd = INVALID_SOCKET; tunnel->server_socket = INVALID_SOCKET; tunnel->dest.host_name = NULL; tunnel->dest.host_port = port; tunnel->buf_ptr = tunnel->buf; tunnel->buf_len = 0; tunnel->content_length = DEFAULT_CONTENT_LENGTH - 1; /* tunnel->in_total_raw = 0; tunnel->in_total_data = 0; tunnel->out_total_raw = 0; tunnel->out_total_data = 0; */ tunnel->strict_content_length=FALSE; tunnel->bytes = 0; tunnel->server_socket = server_socket (port); if ( tunnel->server_socket == INVALID_SOCKET) return NULL; return tunnel; }
int main(int argc, char *argv[]) { int soc; /* 引数にポート番号が指定されているか? */ if (argc <= 1) { (void) fprintf(stderr,"server port\n"); return (EX_USAGE); } /* サーバソケットの準備 */ if ((soc = server_socket(argv[1])) == -1) { (void) fprintf(stderr,"server_socket(%s):error\n", argv[1]); return (EX_UNAVAILABLE); } (void) fprintf(stdout, "ready for accept\n"); /* アクセプトループ */ accept_loop(soc); /* for (;;) { */ /* (void) fprintf(stdout, "just sleep\n"); */ /* sleep(5); */ /* } */ /* ソケットクローズ */ (void) close(soc); return (EX_OK); }
void ServerController::start_server() { is_server_running = true; // Create thread for consuming process std::thread consumer_thread(&ServerController::consume_command, this); consumer_thread.detach(); //Create server socket ServerSocket server_socket(port_number); while (true) { try { std::cerr << "Server listening" << "\n"; std::shared_ptr<Socket> socket_client = nullptr; while ((socket_client = server_socket.accept()) != nullptr) { std::thread handler_thread(&ServerController::handle_client, this, socket_client); handler_thread.detach(); std::cerr << "Server listening again" << "\n"; } } catch (const std::exception& ex) { std::cerr << ex.what() << ", resuming..." << "\n"; } } }
int HttpServer<ServerContext, RequestFactory>::main(const std::vector<std::string>& args) { Poco::Net::ServerSocket server_socket(config().getInt("Service.port", port_)); Poco::Net::HTTPServer http_server( new RequestFactory(context_), server_socket, new Poco::Net::HTTPServerParams); http_server.start(); waitForTerminationRequest(); http_server.stop(); return Poco::Util::Application::EXIT_OK; }
int ctl_socket_init(void) { int s = server_socket(); if (s < 0) return -1; ctl_handler.fd = s; ctl_handler.handler = ctl_rcv_handler; TST(add_epoll(&ctl_handler) == 0, -1); return 0; }
int start_server() { int soc; if ((soc = server_socket(PORT)) == -1) { (void) fprintf(stderr, "server_socket(%s):error\n", PORT); return (EX_UNAVAILABLE); } (void) fprintf(stderr, "ready for accept\n"); accept_loop(soc); (void) close(soc); return 0; }
void engine_init (engine_t *E, const char *const pwd_filename, int index_mode) { E->sfd = 0; struct sigaction sa; memset (&sa, 0, sizeof (sa)); sa.sa_handler = sigusr1_handler; sigemptyset (&sa.sa_mask); sigaction (SIGUSR1, &sa, NULL); sa.sa_handler = sigrtmax_handler; sigaction (SIGRTMAX, &sa, NULL); if (!index_mode && port < PRIVILEGED_TCP_PORTS) { E->sfd = server_socket (port, E->settings_addr, backlog, 0); if (E->sfd < 0) { kprintf ("cannot open server socket at port %d: %m\n", port); exit (1); } } const int gap = 16; if (getuid ()) { struct rlimit rlim; if (getrlimit (RLIMIT_NOFILE, &rlim) < 0) { kprintf ("%s: getrlimit (RLIMIT_NOFILE) fail. %m\n", __func__); exit (1); } if (maxconn > rlim.rlim_cur - gap) { maxconn = rlim.rlim_cur - gap; } } else { if (raise_file_rlimit (maxconn + gap) < 0) { kprintf ("fatal: cannot raise open file limit to %d\n", maxconn + gap); exit (1); } } aes_load_pwd_file (pwd_filename); if (change_user (username) < 0) { kprintf ("fatal: cannot change user to %s\n", username ? username : "******"); exit (1); } init_dyn_data (); if (udp_enabled) { init_server_PID (get_my_ipv4 (), port); } }
int main(int argc, char *argv[], char *envp[]) { struct sigaction sa; int soc; /* 引数にポート番号が指定されているか? */ if (argc <= 1) { (void) fprintf(stderr,"re-exec port\n"); return (EX_USAGE); } if (argc == 3) { (void) fprintf(stderr,"skip daemonize\n"); } else { /* デーモン化 */ (void) daemonize(0, 0); } /* コマンドライン引数、環境変数のアドレスをグローバルに保持 */ argc_ = &argc; argv_ = &argv; envp_ = &envp; /* SIGHUPのシグナルハンドラを指定 */ (void) sigaction(SIGHUP, (struct sigaction *) NULL, &sa); sa.sa_handler = sig_hangup_handler; sa.sa_flags = SA_NODEFER; (void) sigaction(SIGHUP, &sa, (struct sigaction *) NULL); (void) fprintf(stderr, "sigaction():end\n"); /* サーバソケットの準備 */ if ((soc = server_socket(argv[1])) == -1) { (void) fprintf(stderr,"server_socket(%s):error\n", argv[1]); return (EX_UNAVAILABLE); } (void) fprintf(stderr, "ready for accept\n"); /* アクセプトループ */ accept_loop(soc); /* ソケットクローズ */ (void) close(soc); return (EX_OK); }
int server() { char buffer[1024]; int ss = server_socket("127.0.0.1", "9991"); if (ss < 0) { logging(LOG_ERROR, "socket error!"); return -1; } int ns = tcptoaccept(ss, 100000); if (ns < 0) { logging(LOG_ERROR, "accept error!"); return -1; } tcpnonblock(ns); tcpnodelay(ns); tcptoread(ns, buffer, 10, 3000); /*printf("read ok %d !!\n", n); */ /*printf("read data: \n%s\n", buffer); */ assert(strcmp("helloworl", buffer) == 0); tcpclose(ns); tcpclose(ss); return 0; }
void SG_Server::init(char* args[]) { /* struct sigaction sa; struct addrinfo hints, *servinfo, *p; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; int truVal = 1; int status = 0; while((status = getaddrinfo(NULL, args[1], &hints, &servinfo)) != 0 ) { errx(-1, "%s",gai_strerror(status)); } for(p = servinfo; p != NULL; p = p->ai_next) { if (((sockfd) = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { continue; } if ((status = setsockopt((sockfd), SOL_SOCKET, SO_REUSEADDR, &truVal, sizeof(int))) == -1) { errx(-2, "%s",gai_strerror(status)); } if (bind((sockfd), p->ai_addr, p->ai_addrlen) == -1) { close((sockfd)); continue; } break; } if (p == NULL) { errx(-3, "%s", "Initialization failed\n"); } //Start listening if (listen(sockfd, BACKLOG) == -1) { perror("Listen error"); errx(-4, "%s", "Listening Failed\n"); } //(sa).sa_handler = sigchld_handler(0); // reap all dead processes sigemptyset(&((sa).sa_mask)); (sa).sa_flags = SA_RESTART; if (sigaction(SIGCHLD, NULL, &sa) == -1) { errx(-5, "%s", "Handler Failed\n"); } cerr << "[INIT] Server Initilized on port " << port << endl; int maxSocket = listener; FD_SET(listener, &safeSet); FD_SET(0, &safeSet); cerr << "[INIT] Server is up and runnig...\n\n"; */ ServerSocket server_socket ( 30000 ); server = server_socket; }
void start_server (void) { char buf[64]; int i, prev_time = 0; init_epoll (); init_netbuffers (); if (!sfd) { sfd = server_socket (port, settings_addr, backlog, 0); } if (sfd < 0) { kprintf ("cannot open server socket at port %d: %m\n", port); exit (3); } vkprintf (1, "created listening socket at %s:%d, fd=%d\n", conv_addr (settings_addr.s_addr, buf), port, sfd); if (daemonize) { setsid (); } if (change_user (username) < 0) { kprintf ("fatal: cannot change user to %s\n", username ? username : "******"); exit (1); } if (binlogname && !binlog_disabled) { assert (append_to_binlog (Binlog) == log_readto_pos); } init_listening_connection (sfd, &ct_rpc_server, ©exec_result_rpc_server); sigset_t signal_set; sigemptyset (&signal_set); sigaddset (&signal_set, SIGINT); sigaddset (&signal_set, SIGTERM); sigaddset (&signal_set, SIGUSR1); if (daemonize) { sigaddset (&signal_set, SIGHUP); } struct sigaction act; act.sa_handler = copyexec_results_sig_handler; act.sa_mask = signal_set; act.sa_flags = 0; for (i = 1; i <= SIGRTMAX; i++) { if (sigismember (&signal_set, i)) { if (sigaction (i, &act, NULL) < 0) { kprintf ("sigaction (%d) failed. %m\n", i); exit (1); } } } for (i = 0; ; i++) { if (!(i & 255)) { vkprintf (1, "epoll_work(): %d out of %d connections, network buffers: %d used, %d out of %d allocated\n", active_connections, maxconn, NB_used, NB_alloc, NB_max); } epoll_work (71); if (interrupted_by_term_signal ()) { break; } if (pending_signals & (1LL << SIGHUP)) { pending_signals_clear_bit (&signal_set, SIGHUP); kprintf ("got SIGHUP.\n"); sync_binlog (2); } if (pending_signals & (1LL << SIGUSR1)) { pending_signals_clear_bit (&signal_set, SIGUSR1); kprintf ("got SIGUSR1, rotate logs.\n"); reopen_logs (); sync_binlog (2); } if (now != prev_time) { prev_time = now; cron (); } if (quit_steps && !--quit_steps) break; } epoll_close (sfd); close (sfd); flush_binlog_last (); sync_binlog (2); }
int main(int argc, char *argv[]){ //Check if valid format if(argc != 4){ printf("\n\nUsage: ./server <certificate> <key> <port number>\n\n"); exit(1); } //Initialization SSL_CTX *ctx; int server; char *port; SSL_library_init(); //Get the port from the argument port = argv[3]; //Initialize the OpenSSL (page 1) ctx = initialize_server(); //Load and validate the certificate and key (page 1) if(SSL_CTX_use_certificate_file(ctx, argv[1], SSL_FILETYPE_PEM) <= 0){ printf("\n\nERROR: SSL_CTX_use_certificate_file failed (server.c - main)\n"); printf("Could not find the certificate file.\n\n"); exit(1); } if(SSL_CTX_use_PrivateKey_file(ctx, argv[2], SSL_FILETYPE_PEM) <= 0){ printf("\n\nERROR: SSL_CTX_use_PrivateKey_file failed (server.c - main)\n"); printf("Could not find the private key file or incorrect key.\n\n"); exit(1); } if(!SSL_CTX_check_private_key(ctx)){ printf("\n\nERROR: SSL_CTX_check_private_key failed (server.c -main)\n"); printf("Private key does not match the public certificate\n\n"); exit(1); } //create server socket server = server_socket(atoi(port)); //Continue listening while(1){ struct sockaddr_in addr; socklen_t addrLen = sizeof(addr); SSL *ssl; //If client connects int client = accept(server, (struct sockaddr*) &addr, &addrLen); if(client < 0){ printf("\n\nERROR: accept() failed (server.c - main).\n\n"); printf("Couldn't create socket.\n\n"); exit(1); } //creates a new SSL structure to hold the data for SSL connection ssl = SSL_new(ctx); if(ssl == NULL){ printf("\n\nERROR: SSL_new() failed (server.c - main).\n\n"); printf("Couldn't create new SSL structure.\n\n"); exit(1); } //Sets the file descriptor client as the input/output facility for the SSL (encrypted) side of ssl SSL_set_fd(ssl, client); //Start talking ssl_handshake(ssl); } //close and exit close(server); SSL_CTX_free(ctx); return 0; }
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; }
static int server_socket(unsigned *port) { int fd = socket(PF_INET6, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_TCP); if (fd == -1) return -1; struct sockaddr_in6 addr = { .sin6_family = AF_INET6, #ifdef HAVE_SA_LEN .sin6_len = sizeof (addr), #endif .sin6_addr = in6addr_loopback, }; socklen_t addrlen = sizeof (addr); if (bind(fd, (struct sockaddr *)&addr, addrlen) || getsockname(fd, (struct sockaddr *)&addr, &addrlen)) { close(fd); return -1; } *port = ntohs(addr.sin6_port); return fd; } int main(void) { char *url; unsigned port; bool two = false; /* Test bad URLs */ vlc_https_connect_proxy(NULL, "www.example.com", 0, &two, "/test"); vlc_https_connect_proxy(NULL, "www.example.com", 0, &two, "ftp://proxy.example.com/"); int lfd = server_socket(&port); if (lfd == -1) return 77; if (asprintf(&url, "http://[::1]:%u", port) < 0) url = NULL; assert(url != NULL); /* Test connection failure */ vlc_https_connect_proxy(NULL, "www.example.com", 0, &two, url); if (listen(lfd, 255)) { close(lfd); return 77; } vlc_thread_t th; if (vlc_clone(&th, proxy_thread, (void*)(intptr_t)lfd, VLC_THREAD_PRIORITY_LOW)) assert(!"Thread error"); /* Test proxy error */ vlc_https_connect_proxy(NULL, "www.example.com", 0, &two, url); vlc_cancel(th); vlc_join(th, NULL); assert(connection_count > 0); free(url); close(lfd); }
int main (int argc, char **argv) { int s = -1; int fd = -1; Arguments arg; Tunnel *tunnel; int closed; parse_arguments (argc, argv, &arg); if ((debug_level == 0 || debug_file != NULL) && arg.use_daemon) daemon (0, 1); #ifdef DEBUG_MODE if (debug_level != 0 && debug_file == NULL) debug_file = stderr; #else openlog ("htc", LOG_PID, LOG_DAEMON); #endif log_notice ("htc (%s) %s started with arguments:", PACKAGE, VERSION); log_notice (" me = %s", arg.me); log_notice (" device = %s", arg.device ? arg.device : "(null)"); log_notice (" host_name = %s", arg.host_name ? arg.host_name : "(null)"); log_notice (" host_port = %d", arg.host_port); log_notice (" proxy_name = %s", arg.proxy_name ? arg.proxy_name : "(null)"); log_notice (" proxy_port = %d", arg.proxy_port); log_notice (" proxy_buffer_size = %d", arg.proxy_buffer_size); log_notice (" proxy_buffer_timeout = %d", arg.proxy_buffer_timeout); log_notice (" content_length = %d", arg.content_length); log_notice (" forward_port = %d", arg.forward_port); log_notice (" max_connection_age = %d", arg.max_connection_age); log_notice (" use_std = %d", arg.use_std); log_notice (" strict_content_length = %d", arg.strict_content_length); log_notice (" keep_alive = %d", arg.keep_alive); log_notice (" proxy_authorization = %s", arg.proxy_authorization ? arg.proxy_authorization : "(null)"); log_notice (" user_agent = %s", arg.user_agent ? arg.user_agent : "(null)"); log_notice (" debug_level = %d", debug_level); if (arg.forward_port != -1) { struct in_addr addr; addr.s_addr = INADDR_ANY; s = server_socket (addr, arg.forward_port, 0); log_debug ("server_socket (%d) = %d", arg.forward_port, s); if (s == -1) { log_error ("couldn't create server socket: %s", strerror (errno)); log_exit (1); } } #ifdef DEBUG_MODE signal (SIGPIPE, log_sigpipe); #else signal (SIGPIPE, SIG_IGN); #endif for (;;) { time_t last_tunnel_write; if (arg.device) { fd = open_device (arg.device); log_debug ("open_device (\"%s\") = %d", arg.device, fd); if (fd == -1) { log_error ("couldn't open %s: %s", arg.device, strerror (errno)); log_exit (1); } /* Check that fd is not 0 (clash with --stdin-stdout) */ if (fd == 0) { log_notice("changing fd from %d to 3",fd); if (dup2 (fd, 3) != 3) { log_error ("couldn't dup2 (%d, 3): %s",fd,strerror(errno)); log_exit (1); } } } else if (arg.forward_port != -1) { log_debug ("waiting for connection on port %d", arg.forward_port); fd = wait_for_connection_on_socket (s); log_debug ("wait_for_connection_on_socket (%d) = %d", s, fd); if (fd == -1) { log_error ("couldn't forward port %d: %s", arg.forward_port, strerror (errno)); log_exit (1); } /* Check that fd is not 0 (clash with --stdin-stdout) */ if (fd == 0) { log_notice ("changing fd from %d to 3",fd); if (dup2 (fd, 3) != 3) { log_error ("couldn't dup2 (%d, 3): %s",fd,strerror(errno)); log_exit (1); } } } else if (arg.use_std) { log_debug ("using stdin as fd"); fd = 0; if (fcntl(fd,F_SETFL,O_NONBLOCK)==-1) { log_error ("couldn't set stdin to non-blocking mode: %s", strerror(errno)); log_exit (1); } /* Usage of stdout (fd = 1) is checked later. */ } log_debug ("creating a new tunnel"); tunnel = tunnel_new_client (arg.host_name, arg.host_port, arg.proxy_name, arg.proxy_port, arg.content_length); if (tunnel == NULL) { log_error ("couldn't create tunnel"); log_exit (1); } if (tunnel_setopt (tunnel, "strict_content_length", &arg.strict_content_length) == -1) log_debug ("tunnel_setopt strict_content_length error: %s", strerror (errno)); if (tunnel_setopt (tunnel, "keep_alive", &arg.keep_alive) == -1) log_debug ("tunnel_setopt keep_alive error: %s", strerror (errno)); if (tunnel_setopt (tunnel, "max_connection_age", &arg.max_connection_age) == -1) log_debug ("tunnel_setopt max_connection_age error: %s", strerror (errno)); if (arg.proxy_authorization != NULL) { ssize_t len; char *auth; len = encode_base64 (arg.proxy_authorization, strlen (arg.proxy_authorization), &auth); if (len == -1) { log_error ("encode_base64 error: %s", strerror (errno)); } else { char *str = malloc (len + 7); if (str == NULL) { log_error ("out of memory when encoding " "authorization string"); log_exit (1); } strcpy (str, "Basic "); strcat (str, auth); free (auth); if (tunnel_setopt (tunnel, "proxy_authorization", str) == -1) log_error ("tunnel_setopt proxy_authorization error: %s", strerror (errno)); free (str); } } if (arg.user_agent != NULL) { if (tunnel_setopt (tunnel, "user_agent", arg.user_agent) == -1) log_error ("tunnel_setopt user_agent error: %s", strerror (errno)); } if (tunnel_connect (tunnel) == -1) { log_error ("couldn't open tunnel: %s", strerror (errno)); log_exit (1); } if (arg.proxy_name) log_notice ("connected to %s:%d via %s:%d", arg.host_name, arg.host_port, arg.proxy_name, arg.proxy_port); else log_notice ("connected to %s:%d", arg.host_name, arg.host_port); closed = FALSE; time (&last_tunnel_write); while (!closed) { struct pollfd pollfd[2]; int keep_alive_timeout; int timeout; time_t t; int n; pollfd[0].fd = fd; pollfd[0].events = POLLIN; pollfd[1].fd = tunnel_pollin_fd (tunnel); pollfd[1].events = POLLIN; time (&t); timeout = 1000 * (arg.keep_alive - (t - last_tunnel_write)); keep_alive_timeout = TRUE; if (timeout < 0) timeout = 0; if (arg.proxy_buffer_timeout != -1 && arg.proxy_buffer_timeout < timeout) { timeout = arg.proxy_buffer_timeout; keep_alive_timeout = FALSE; } log_annoying ("poll () ..."); n = poll (pollfd, 2, timeout); log_annoying ("... = %d", n); if (n == -1) { log_error ("poll error: %s", strerror (errno)); log_exit (1); } else if (n == 0) { log_verbose ("poll() timed out"); if (keep_alive_timeout) { tunnel_padding (tunnel, 1); time (&last_tunnel_write); } else { if (tunnel_maybe_pad (tunnel, arg.proxy_buffer_size) > 0) time (&last_tunnel_write); } continue; } handle_input ("device or port", tunnel, fd, pollfd[0].revents, handle_device_input, &closed); handle_input ("tunnel", tunnel, fd, pollfd[1].revents, handle_tunnel_input, &closed); if (pollfd[0].revents & POLLIN) time (&last_tunnel_write); } log_debug ("destroying tunnel"); if (fd != 0) { close (fd); } tunnel_destroy (tunnel); if (arg.proxy_name) log_notice ("disconnected from %s:%d via %s:%d", arg.host_name, arg.host_port, arg.proxy_name, arg.proxy_port); else log_notice ("disconnected from %s%d", arg.host_name, arg.host_port); } log_debug ("closing server socket"); close (s); log_exit (0); }
int main (int argc, char **argv) { int c; int l_socket; conn *l_conn; struct in_addr addr; int lock_memory = 0; int daemonize = 0; /* initialize stuff */ event_init(); stats_init(); assoc_init(); settings_init(); conn_init(); /* process arguments */ while ((c = getopt(argc, argv, "p:s:m:c:khdl:")) != -1) { switch (c) { case 'p': settings.port = atoi(optarg); break; case 's': settings.maxitems = atoi(optarg); break; case 'm': settings.maxbytes = atoi(optarg)*1024*1024; break; case 'c': settings.maxconns = atoi(optarg); break; case 'h': usage(); exit(0); case 'k': lock_memory = 1; break; case 'l': if (!inet_aton(optarg, &addr)) { fprintf(stderr, "Illegal address: %s\n", optarg); return 1; } else { settings.interface = addr; } break; case 'd': daemonize = 1; break; default: fprintf(stderr, "Illegal argument \"%c\"\n", c); return 1; } } if (daemonize) { int child; child = fork(); if (child == -1) { fprintf(stderr, "failed to fork() in order to daemonize\n"); return 1; } if (child) { /* parent */ exit(0); } else { /* child */ setsid(); /* become a session group leader */ child = fork(); /* stop being a session group leader */ if (child) { /* parent */ exit(0); } else { int null; chdir("/"); null = open("/dev/null", O_RDWR); dup2(null, 0); dup2(null, 1); dup2(null, 2); close(null); } } } /* lock paged memory if needed */ if (lock_memory) { mlockall(MCL_CURRENT | MCL_FUTURE); } /* create the listening socket and bind it */ l_socket = server_socket(settings.port); if (l_socket == -1) { fprintf(stderr, "failed to listen\n"); exit(1); } /* create the initial listening connection */ if (!(l_conn = conn_new(l_socket, conn_listening, EV_READ | EV_PERSIST))) { fprintf(stderr, "failed to create listening connection"); exit(1); } /* initialise deletion array and timer event */ deltotal = 200; delcurr = 0; todelete = malloc(sizeof(item *)*deltotal); delete_handler(0,0,0); /* sets up the event */ /* enter the loop */ event_loop(0); return; }
int main (int argc, char **argv) { int c; conn *l_conn; struct in_addr addr; int lock_memory = 0; int daemonize = 0; int maxcore = 0; char *username = 0; struct passwd *pw; struct sigaction sa; struct rlimit rlim; char *pid_file = NULL; /* init settings */ settings_init(); /* process arguments */ while ((c = getopt(argc, argv, "p:m:Mc:khirvdl:u:P:")) != -1) { switch (c) { case 'p': settings.port = atoi(optarg); break; case 'm': settings.maxbytes = atoi(optarg)*1024*1024; break; case 'M': settings.evict_to_free = 0; break; case 'c': settings.maxconns = atoi(optarg); break; case 'h': usage(); exit(0); case 'i': usage_license(); exit(0); case 'k': lock_memory = 1; break; case 'v': settings.verbose++; break; case 'l': if (!inet_aton(optarg, &addr)) { fprintf(stderr, "Illegal address: %s\n", optarg); return 1; } else { settings.interface = addr; } break; case 'd': daemonize = 1; break; case 'r': maxcore = 1; break; case 'u': username = optarg; break; case 'P': pid_file = optarg; break; default: fprintf(stderr, "Illegal argument \"%c\"\n", c); return 1; } } if (maxcore) { struct rlimit rlim_new; /* * First try raising to infinity; if that fails, try bringing * the soft limit to the hard. */ if (getrlimit(RLIMIT_CORE, &rlim)==0) { rlim_new.rlim_cur = rlim_new.rlim_max = RLIM_INFINITY; if (setrlimit(RLIMIT_CORE, &rlim_new)!=0) { /* failed. try raising just to the old max */ rlim_new.rlim_cur = rlim_new.rlim_max = rlim.rlim_max; (void) setrlimit(RLIMIT_CORE, &rlim_new); } } /* * getrlimit again to see what we ended up with. Only fail if * the soft limit ends up 0, because then no core files will be * created at all. */ if ((getrlimit(RLIMIT_CORE, &rlim)!=0) || rlim.rlim_cur==0) { fprintf(stderr, "failed to ensure corefile creation\n"); exit(1); } } /* * If needed, increase rlimits to allow as many connections * as needed. */ if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) { fprintf(stderr, "failed to getrlimit number of files\n"); exit(1); } else { int maxfiles = settings.maxconns; if (rlim.rlim_cur < maxfiles) rlim.rlim_cur = maxfiles + 3; if (rlim.rlim_max < rlim.rlim_cur) rlim.rlim_max = rlim.rlim_cur; if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) { fprintf(stderr, "failed to set rlimit for open files. Try running as root or requesting smaller maxconns value.\n"); exit(1); } } /* * initialization order: first create the listening socket * (may need root on low ports), then drop root if needed, * then daemonise if needed, then init libevent (in some cases * descriptors created by libevent wouldn't survive forking). */ /* create the listening socket and bind it */ l_socket = server_socket(settings.port); if (l_socket == -1) { fprintf(stderr, "failed to listen\n"); exit(1); } /* lose root privileges if we have them */ if (getuid()== 0 || geteuid()==0) { if (username==0 || *username=='\0') { fprintf(stderr, "can't run as root without the -u switch\n"); return 1; } if ((pw = getpwnam(username)) == 0) { fprintf(stderr, "can't find the user %s to switch to\n", username); return 1; } if (setgid(pw->pw_gid)<0 || setuid(pw->pw_uid)<0) { fprintf(stderr, "failed to assume identity of user %s\n", username); return 1; } } /* daemonize if requested */ /* if we want to ensure our ability to dump core, don't chdir to / */ if (daemonize) { int res; res = daemon(maxcore, settings.verbose); if (res == -1) { fprintf(stderr, "failed to daemon() in order to daemonize\n"); return 1; } } /* initialize other stuff */ item_init(); event_init(); stats_init(); assoc_init(); conn_init(); slabs_init(settings.maxbytes); /* lock paged memory if needed */ if (lock_memory) { #ifdef HAVE_MLOCKALL mlockall(MCL_CURRENT | MCL_FUTURE); #else fprintf(stderr, "warning: mlockall() not supported on this platform. proceeding without.\n"); #endif } /* * ignore SIGPIPE signals; we can use errno==EPIPE if we * need that information */ sa.sa_handler = SIG_IGN; sa.sa_flags = 0; if (sigemptyset(&sa.sa_mask) == -1 || sigaction(SIGPIPE, &sa, 0) == -1) { perror("failed to ignore SIGPIPE; sigaction"); exit(1); } /* create the initial listening connection */ if (!(l_conn = conn_new(l_socket, conn_listening, EV_READ | EV_PERSIST))) { fprintf(stderr, "failed to create listening connection"); exit(1); } /* initialise deletion array and timer event */ deltotal = 200; delcurr = 0; todelete = malloc(sizeof(item *)*deltotal); delete_handler(0,0,0); /* sets up the event */ /* save the PID in if we're a daemon */ if (daemonize) save_pid(getpid(),pid_file); /* enter the loop */ event_loop(0); /* remove the PID file if we're a daemon */ if (daemonize) remove_pidfile(pid_file); return 0; }
void server_init (engine_t *E, server_functions_t *F, conn_type_t *listen_connection_type, void *listen_connection_extra) { if (F != NULL) { if (F->sighup) { sf.sighup = F->sighup; } if (F->sigusr1) { sf.sigusr1 = F->sigusr1; } if (F->save_index) { sf.save_index = F->save_index; } if (F->cron) { sf.cron = F->cron; } } init_epoll (); init_netbuffers (); if (udp_enabled) { init_msg_buffers (0); } if (daemonize) { setsid (); reopen_logs (); } if (!E->sfd) { E->sfd = server_socket (port, E->settings_addr, backlog, 0); } if (E->sfd < 0) { kprintf ("cannot open server socket at port %d: %m\n", port); exit (1); } if (change_user (username) < 0) { kprintf ("fatal: cannot change user to %s\n", username ? username : "******"); exit (1); } if (binlogname && !binlog_disabled) { assert (append_to_binlog (Binlog) == log_readto_pos); } init_listening_connection (E->sfd, listen_connection_type, listen_connection_extra); if (udp_enabled) { add_udp_socket (port, 0); } if (binlog_disabled && binlog_fd >= 0) { epoll_pre_event = read_new_events; } struct sigaction sa; memset (&sa, 0, sizeof (sa)); sa.sa_handler = sigint_handler; sigemptyset (&sa.sa_mask); sigaddset (&sa.sa_mask, SIGTERM); sigaction (SIGINT, &sa, NULL); sa.sa_handler = sigterm_handler; sigemptyset (&sa.sa_mask); sigaddset (&sa.sa_mask, SIGINT); sigaction (SIGTERM, &sa, NULL); sa.sa_handler = SIG_IGN; sigaction (SIGPIPE, &sa, NULL); sigaction (SIGPOLL, &sa, NULL); if (daemonize) { sa.sa_handler = sighup_handler; sigemptyset (&sa.sa_mask); sigaction (SIGHUP, &sa, NULL); } }
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; int nready, i; int videosize, videoleft; int recvd, sent; char urlhost[URLSIZE], urlpath[URLSIZE], tempstr[URLSIZE]; unsigned char msgbuf[BUFSIZE], sendbuf[BUFSIZE]; char *temp; RTSPMsg rtspmsg; Client streamclient; /* The current state of the protocol */ int mediastate = IDLE; int quit = 0; 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, NULL)) == -1) { write_log(logfd, "Select interrupted by a signal\n"); } for (i = 0; i <= maxfd; i++) { if (FD_ISSET(i, &readfds)) { nready--; /* New connection from a client */ if (i == listenfd) { 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) 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); 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); printf("Socket closed\n"); } writestr(videofd, msgbuf, recvd); videoleft -= recvd; if (videoleft <= 0) mediastate = STREAM; break; /* TODO: Start streaming, currently just exits the program */ case STREAM: /* close(videofd); close(mediafd); close(listenfd); quit = 1; */ break; default: break; } } /* Data from a client ( i == streamclient.rtspfd) */ else { if ((recvd = recv_all(i, msgbuf, BUFSIZE, 0)) == 0) { FD_CLR(i, &masterfds); close(i); printf("Socket closed\n"); streamclient.state = NOCLIENT; } else { printf("%s", msgbuf); parse_rtsp(&rtspmsg, msgbuf); } switch (streamclient.state) { case CLICONNECTED: if (rtspmsg.type == OPTIONS) { sent = rtsp_options(&rtspmsg, sendbuf); send_all(i, sendbuf, sent); } else if (rtspmsg.type == DESCRIBE) { /* 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; /* TODO: parse SDP from the media file rather than hardcoding it */ sent = rtsp_describe(&rtspmsg, sendbuf); send_all(i, sendbuf, sent); streamclient.state = SDPSENT; } break; case SDPSENT: if (rtspmsg.type == SETUP) { sent = rtsp_setup(&rtspmsg, sendbuf, 50508, 50509); send_all(i, sendbuf, sent); write_remote_ip(tempstr, streamclient.rtspfd); resolve_host(tempstr, rtspmsg.clirtpport, 0, SOCK_DGRAM, &info); streamclient.videofds[0] = client_socket(info, 50508); resolve_host(tempstr, rtspmsg.clirtcpport, 0, SOCK_DGRAM, &info); streamclient.videofds[1] = client_socket(info, 50509); streamclient.state = SETUPSENT; } break; case SETUPSENT: if (rtspmsg.type == PLAY) { } break; default: break; } } } if (nready <= 0) break; } } return 1; }