void debug_mprintf (mchar* fmt, ...) { int was_open = 1; va_list argptr; int rc; mchar mbuf[DEBUG_BUF_LEN]; char cbuf[DEBUG_BUF_LEN]; if (!debug_on) return; if (!debug_initialized) { m_debug_lock = threadlib_create_sem(); threadlib_signal_sem(&m_debug_lock); } threadlib_waitfor_sem (&m_debug_lock); va_start (argptr, fmt); if (!gcsfp) { was_open = 0; debug_open(); if (!gcsfp) return; } if (!debug_initialized) { debug_initialized = 1; fprintf (gcsfp, "=========================\n"); fprintf (gcsfp, "STREAMRIPPER " SRPLATFORM " " SRVERSION "\n"); } #if defined HAVE_WCHAR_SUPPORT rc = vswprintf (mbuf, DEBUG_BUF_LEN, fmt, argptr); debug_on = 0; /* Avoid recursive call which hangs on semaphore */ rc = string_from_mstring (cbuf, DEBUG_BUF_LEN, mbuf, CODESET_LOCALE); debug_on = 1; #else rc = vsnprintf (cbuf, DEBUG_BUF_LEN, fmt, argptr); #endif fwrite (cbuf, 1, rc, gcsfp); fflush (gcsfp); va_end (argptr); if (!was_open) { debug_close (); } threadlib_signal_sem (&m_debug_lock); }
debug_printf (char* fmt, ...) #endif { int was_open = 1; va_list argptr; if (!debug_on) { /* Uncomment to debug debug_mprintf() */ #if defined (commentout) va_start (argptr, fmt); vprintf (fmt, argptr); va_end (argptr); #endif return; } if (!debug_initialized) { m_debug_lock = threadlib_create_sem(); threadlib_signal_sem(&m_debug_lock); } threadlib_waitfor_sem (&m_debug_lock); va_start (argptr, fmt); if (!gcsfp) { was_open = 0; debug_open(); if (!gcsfp) return; } if (!debug_initialized) { debug_initialized = 1; fprintf (gcsfp, "=========================\n"); fprintf (gcsfp, "STREAMRIPPER " SRPLATFORM " " SRVERSION "\n"); } vfprintf (gcsfp, fmt, argptr); fflush (gcsfp); va_end (argptr); if (!was_open) { debug_close (); } threadlib_signal_sem (&m_debug_lock); }
void debug_printf(char *fmt, ...) { int was_open = 1; va_list argptr; if (!debug_on) { return; } if (!debug_initialized) { m_debug_lock = threadlib_create_sem(); threadlib_signal_sem(&m_debug_lock); } threadlib_waitfor_sem(&m_debug_lock); va_start(argptr, fmt); if (!gcsfp) { was_open = 0; debug_open(); if (!gcsfp) return; } if (!debug_initialized) { debug_initialized = 1; fprintf(gcsfp, "=========================\n"); fprintf(gcsfp, "STREAMRIPPER " SRPLATFORM " " SRVERSION "\n"); } vfprintf(gcsfp, fmt, argptr); fflush(gcsfp); va_end(argptr); if (!was_open) { debug_close(); } threadlib_signal_sem(&m_debug_lock); }
void thread_send (void* arg) { RELAY_LIST* prev; RELAY_LIST* ptr; RELAY_LIST* next; int sock; BOOL good; error_code err = SR_SUCCESS; RIP_MANAGER_INFO* rmi = (RIP_MANAGER_INFO*) arg; RELAYLIB_INFO* rli = &rmi->relaylib_info; while (rli->m_running) { threadlib_waitfor_sem (&rmi->relay_list_sem); ptr = rmi->relay_list; if (ptr != NULL) { prev = NULL; while (ptr != NULL) { sock = ptr->m_sock; next = ptr->m_next; if (swallow_receive(sock) != 0) { good = FALSE; } else { good = send_to_relay (rmi, ptr); } if (!good) { debug_printf ("Relay: Client %d disconnected (%s)\n", sock, strerror(errno)); relaylib_disconnect (rmi, prev, ptr); } else if (ptr != NULL) { prev = ptr; } ptr = next; } } else { err = SR_ERROR_HOST_NOT_CONNECTED; } threadlib_signal_sem (&rmi->relay_list_sem); Sleep (50); } rli->m_running_send = FALSE; }
static void destroy_all_hostsocks (RIP_MANAGER_INFO* rmi) { RELAY_LIST* ptr; threadlib_waitfor_sem (&rmi->relay_list_sem); while (rmi->relay_list != NULL) { ptr = rmi->relay_list; closesocket(ptr->m_sock); rmi->relay_list = ptr->m_next; if (ptr->m_buffer != NULL) { free (ptr->m_buffer); ptr->m_buffer = NULL; } free(ptr); } rmi->relay_list_len = 0; rmi->relay_list = NULL; threadlib_signal_sem (&rmi->relay_list_sem); }
void relaylib_stop (RIP_MANAGER_INFO* rmi) { int ix; RELAYLIB_INFO* rli = &rmi->relaylib_info; debug_printf("relaylib_stop:start\n"); if (!rli->m_running) { debug_printf("***relaylib_stop:return\n"); return; } rli->m_running = FALSE; ix = 0; while (ix<120 && (rli->m_running_accept | rli->m_running_send)) { sleep(1); ++ix; } if (ix==120) { debug_printf ("relay threads refused to end, aborting\n"); fprintf (stderr,"relay threads refused to end, aborting\n"); exit(1); } threadlib_signal_sem (&rli->m_sem_not_connected); if (closesocket(rli->m_listensock) == SOCKET_ERROR) { // JCBUG, what can we do? } /* Accept thread will watch for this and not try to accept anymore */ rli->m_listensock = SOCKET_ERROR; debug_printf ("waiting for relay close\n"); threadlib_waitforclose (&rli->m_hthread_accept); threadlib_waitforclose (&rli->m_hthread_send); destroy_all_hostsocks (rmi); threadlib_destroy_sem (&rli->m_sem_not_connected); debug_printf("relaylib_stop:done!\n"); }
static void ripthread (void *thread_arg) { error_code ret; RIP_MANAGER_INFO* rmi = (RIP_MANAGER_INFO*) thread_arg; debug_ripthread (rmi); debug_stream_prefs (rmi->prefs); /* Connect to remote server */ ret = start_ripping (rmi); if (ret != SR_SUCCESS) { debug_printf ("Ripthread did start_ripping()\n"); threadlib_signal_sem (&rmi->started_sem); post_error (rmi, ret); goto DONE; } rmi->status_callback (rmi, RM_STARTED, (void *)NULL); post_status (rmi, RM_STATUS_BUFFERING); debug_printf ("Ripthread did initialization\n"); threadlib_signal_sem(&rmi->started_sem); while (TRUE) { debug_printf ("Gonna ripstream_rip\n"); ret = ripstream_rip(rmi); debug_printf ("Did ripstream_rip\n"); if (!rmi->started) { break; } else if (rmi->megabytes_ripped >= rmi->prefs->maxMB_rip_size && GET_CHECK_MAX_BYTES (rmi->prefs->flags)) { /* GCS Aug 23, 2003: bytes_ripped can still overflow */ socklib_close (&rmi->stream_sock); destroy_subsystems (rmi); //post_error (rmi, SR_ERROR_MAX_BYTES_RIPPED); break; } else if (ret == SR_SUCCESS_BUFFERING) { post_status (rmi, RM_STATUS_BUFFERING); /* Fall through */ } else if (ret == SR_ERROR_CANT_DECODE_MP3) { post_error (rmi, ret); continue; } else if ((ret == SR_ERROR_RECV_FAILED || ret == SR_ERROR_TIMEOUT || ret == SR_ERROR_NO_TRACK_INFO || ret == SR_ERROR_SELECT_FAILED) && GET_AUTO_RECONNECT (rmi->prefs->flags)) { /* Try to reconnect */ post_status (rmi, RM_STATUS_RECONNECTING); while (rmi->started) { socklib_close(&rmi->stream_sock); if (rmi->ep) { debug_printf ("Close external\n"); close_external (&rmi->ep); } destroy_subsystems (rmi); ret = start_ripping (rmi); if (ret == SR_SUCCESS) break; Sleep(1000); } if (!rmi->started) { break; } /* Fall through */ } else if (ret == SR_ERROR_ABORT_PIPE_SIGNALLED) { /* Normal exit condition CTRL-C on unix */ destroy_subsystems (rmi); break; } else if (ret != SR_SUCCESS) { destroy_subsystems (rmi); post_error (rmi, ret); break; } /* All systems go. Caller should update GUI that it is ripping */ if (rmi->filesize > 0) { post_status (rmi, RM_STATUS_RIPPING); } } // We get here when there was either a fatal error // or we we're not auto-reconnecting and the stream just stopped // or when we have been told to stop, via the rmi->started flag DONE: rmi->status_callback (rmi, RM_DONE, 0); rmi->started = 0; debug_printf ("ripthread() exiting!\n"); }
void thread_accept (void* arg) { int ret; int newsock; BOOL good; struct sockaddr_in client; socklen_t iAddrSize = sizeof(client); RELAY_LIST* newhostsock; int icy_metadata; char* client_http_header; RIP_MANAGER_INFO* rmi = (RIP_MANAGER_INFO*) arg; RELAYLIB_INFO* rli = &rmi->relaylib_info; STREAM_PREFS* prefs = rmi->prefs; int have_metadata; if (rmi->http_info.meta_interval == NO_META_INTERVAL) { have_metadata = 0; } else { have_metadata = 1; } debug_printf("thread_accept:start\n"); while (rli->m_running) { fd_set fds; struct timeval tv; // this event will keep use from accepting while we // have a connection active // when a connection gets dropped, or when streamripper shuts down // this event will get signaled debug_printf("thread_accept:waiting on m_sem_not_connected\n"); threadlib_waitfor_sem (&rli->m_sem_not_connected); if (!rli->m_running) { debug_printf("thread_accept:exit (no longer m_running)\n"); break; } // Poll once per second, instead of blocking forever in // accept(), so that we can regain control if relaylib_stop() // called FD_ZERO (&fds); while (rli->m_listensock != SOCKET_ERROR && rli->m_running) { FD_SET (rli->m_listensock, &fds); tv.tv_sec = 1; tv.tv_usec = 0; debug_printf("thread_accept:calling select()\n"); ret = select (rli->m_listensock + 1, &fds, NULL, NULL, &tv); debug_printf("thread_accept:select() returned %d\n", ret); if (ret == 1) { unsigned long num_connected; /* If connections are full, do nothing. Note that m_max_connections is 0 for infinite connections allowed. */ threadlib_waitfor_sem (&rmi->relay_list_sem); num_connected = rmi->relay_list_len; threadlib_signal_sem (&rmi->relay_list_sem); if (prefs->max_connections > 0 && num_connected >= (unsigned long) prefs->max_connections) { continue; } /* Check for connections */ debug_printf ("Calling accept()\n"); newsock = accept (rli->m_listensock, (struct sockaddr *)&client, &iAddrSize); if (newsock != SOCKET_ERROR) { // Got successful accept debug_printf ("Relay: Client %d new from %s:%hu\n", newsock, inet_ntoa(client.sin_addr), ntohs(client.sin_port)); // Socket is new and its buffer had better have // room to hold the entire HTTP header! good = FALSE; if (header_receive (newsock, &icy_metadata) == 0 && rmi->cbuf2.buf != NULL) { int header_len; make_nonblocking (newsock); client_http_header = client_relay_header_generate (rmi, icy_metadata); header_len = strlen (client_http_header); ret = send (newsock, client_http_header, strlen(client_http_header), 0); debug_printf ("Relay: Sent response header to client %d (%d)\n", ret, header_len); client_relay_header_release (client_http_header); if (ret == header_len) { newhostsock = malloc (sizeof(RELAY_LIST)); if (newhostsock != NULL) { // Add new client to list (headfirst) threadlib_waitfor_sem (&rmi->relay_list_sem); newhostsock->m_is_new = 1; newhostsock->m_sock = newsock; newhostsock->m_next = rmi->relay_list; if (have_metadata) { newhostsock->m_icy_metadata = icy_metadata; } else { newhostsock->m_icy_metadata = 0; } rmi->relay_list = newhostsock; rmi->relay_list_len++; threadlib_signal_sem (&rmi->relay_list_sem); good = TRUE; } } } if (!good) { closesocket (newsock); debug_printf ("Relay: Client %d disconnected (Unable to receive HTTP header) or cbuf2.buf is NULL\n", newsock); //if (rmi->cbuf2.buf == NULL) { // debug_printf ("In fact, cbuf2.buf is NULL\n"); //} } } } else if (ret == SOCKET_ERROR) { /* Something went wrong with select */ break; } } threadlib_signal_sem (&rli->m_sem_not_connected); /* loop back up to select */ } rli->m_running_accept = FALSE; rli->m_running = FALSE; }
error_code relaylib_start (RIP_MANAGER_INFO* rmi, BOOL search_ports, u_short relay_port, u_short max_port, u_short *port_used, char *if_name, int max_connections, char *relay_ip, int have_metadata) { int ret; #ifdef WIN32 WSADATA wsd; #endif RELAYLIB_INFO* rli = &rmi->relaylib_info; /* GCS: These were globally initialized... */ rli->m_listensock = SOCKET_ERROR; rli->m_running = FALSE; rli->m_running_accept = FALSE; rli->m_running_send = FALSE; debug_printf ("relaylib_start()\n"); rmi->relay_list = 0; rmi->relay_list_len = 0; #ifdef WIN32 if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) { debug_printf ("relaylib_init(): SR_ERROR_CANT_BIND_ON_PORT\n"); return SR_ERROR_CANT_BIND_ON_PORT; } #endif if (relay_port < 1 || !port_used) { debug_printf ("relaylib_init(): SR_ERROR_INVALID_PARAM\n"); return SR_ERROR_INVALID_PARAM; } #ifndef WIN32 // catch a SIGPIPE if send fails signal(SIGPIPE, catch_pipe); #endif rli->m_sem_not_connected = threadlib_create_sem(); rmi->relay_list_sem = threadlib_create_sem(); threadlib_signal_sem (&rmi->relay_list_sem); // NOTE: we need to signal it here in case we try to destroy // relaylib before the thread starts! threadlib_signal_sem (&rli->m_sem_not_connected); //m_max_connections = max_connections; //m_have_metadata = have_metadata; *port_used = 0; if (!search_ports) max_port = relay_port; for(;relay_port <= max_port; relay_port++) { ret = try_port (rli, (u_short) relay_port, if_name, relay_ip); if (ret == SR_ERROR_CANT_BIND_ON_PORT) continue; // Keep searching. if (ret == SR_SUCCESS) { *port_used = relay_port; debug_printf ("Relay: Listening on port %d\n", relay_port); ret = SR_SUCCESS; if (!rli->m_running) { ret = relaylib_start_threads (rmi); } return ret; } else { return ret; } } return SR_ERROR_CANT_BIND_ON_PORT; }