예제 #1
0
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);
}
예제 #2
0
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);
}
예제 #3
0
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);
}
예제 #4
0
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;
}
예제 #5
0
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);
}
예제 #6
0
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");
}
예제 #7
0
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");
}
예제 #8
0
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;
}
예제 #9
0
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;
}