예제 #1
0
void irc_destroy_session (irc_session_t * session)
{
	if ( session->sock >= 0 )
		socket_close (&session->sock);

	if ( session->realname )
		free (session->realname);

	if ( session->username )
		free (session->username);

	if ( session->nick )
		free (session->nick);

	if ( session->server )
		free (session->server);

	if ( session->server_password )
		free (session->server_password);

#if defined (ENABLE_THREADS)
	libirc_mutex_destroy (&session->mutex_session);
#endif

	/*
	 * delete DCC data
	 * libirc_remove_dcc_session removes the DCC session from the list.
	 */
	while ( session->dcc_sessions )
		libirc_remove_dcc_session (session, session->dcc_sessions, 0);

	free (session);
}
예제 #2
0
void irc_destroy_session (irc_session_t * session)
{
	free_ircsession_strings( session );

	// The CTCP VERSION must be freed only now
	if ( session->ctcp_version )
		free (session->ctcp_version);

	if ( session->sock >= 0 )
		socket_close (&session->sock);

#if defined (ENABLE_THREADS)
	libirc_mutex_destroy (&session->mutex_session);
#endif

#if defined (ENABLE_SSL)
	if ( session->ssl )
		SSL_free( session->ssl );
#endif

	/*
	 * delete DCC data
	 * libirc_remove_dcc_session removes the DCC session from the list.
	 */
	while ( session->dcc_sessions )
		libirc_remove_dcc_session (session, session->dcc_sessions, 0);

	libirc_mutex_destroy (&session->mutex_dcc);

	free (session);
}
예제 #3
0
int	irc_dcc_chat (irc_session_t * session, void * ctx, const char * nick, irc_dcc_callback_t callback, irc_dcc_t * dccid)
{
	struct sockaddr_in saddr;
	socklen_t len = sizeof(saddr);
	char cmdbuf[128], notbuf[128];
	irc_dcc_session_t * dcc;
	int err;

	if ( session->state != LIBIRC_STATE_CONNECTED )
	{
		session->lasterror = LIBIRC_ERR_STATE;
		return 1;
	}

	err = libirc_new_dcc_session (session, 0, 0, LIBIRC_DCC_CHAT, ctx, &dcc);

	if ( err )
	{
		session->lasterror = err;
		return 1;
	}

	if ( getsockname (dcc->sock, (struct sockaddr*) &saddr, &len) < 0 )
	{
		session->lasterror = LIBIRC_ERR_SOCKET;
		libirc_remove_dcc_session (session, dcc, 1);
		return 1;
	}

	sprintf (notbuf, "DCC Chat (%s)", inet_ntoa (saddr.sin_addr));
	sprintf (cmdbuf, "DCC CHAT chat %lu %u", (unsigned long) ntohl (saddr.sin_addr.s_addr), ntohs (saddr.sin_port));

	if ( irc_cmd_notice (session, nick, notbuf)
	|| irc_cmd_ctcp_request (session, nick, cmdbuf) )
	{
		libirc_remove_dcc_session (session, dcc, 1);
		return 1;
	}

	*dccid = dcc->id;
	dcc->cb = callback;
	dcc->dccmode = LIBIRC_DCC_CHAT;

	return 0;
}
예제 #4
0
파일: dcc.c 프로젝트: TheAomx/xdccget
static void libirc_dcc_add_descriptors(irc_session_t * ircsession) {
    irc_dcc_session_t * dcc, *dcc_next;

    libirc_mutex_lock(&ircsession->mutex_dcc);

    // Preprocessing DCC list:
    // - ask DCC send callbacks for data;
    // - remove unused DCC structures
    for (dcc = ircsession->dcc_sessions; dcc; dcc = dcc_next) {
        dcc_next = dcc->next;

        // Clean up unused sessions
        if (dcc->state == LIBIRC_STATE_REMOVED)
            libirc_remove_dcc_session(ircsession, dcc, 0);
    }

    for (dcc = ircsession->dcc_sessions; dcc; dcc = dcc->next) {
        fdwatch_add_fd(dcc->sock);
        switch (dcc->state) {
            case LIBIRC_STATE_CONNECTING:
                // While connection, only out_set descriptor should be set
                fdwatch_set_fd(dcc->sock, FDW_WRITE);
                break;

            case LIBIRC_STATE_CONNECTED:
                fdwatch_set_fd(dcc->sock, FDW_READ);
                break;

            case LIBIRC_STATE_CONFIRM_SIZE:
                fdwatch_set_fd(dcc->sock, FDW_WRITE);
                break;
            case LIBIRC_STATE_WAITING_FOR_RESUME_ACK:

            break;
            default:
                DBG_WARN("unknown state at libirc_dcc_add_descriptors");
                break;
        }
    }

    libirc_mutex_unlock(&ircsession->mutex_dcc);
}
예제 #5
0
void irc_destroy_session(irc_session_t * session) {
    free_ircsession_strings(session);

    if (session->sock >= 0)
        socket_close(&session->sock);

#if defined (ENABLE_THREADS)
    libirc_mutex_destroy(&session->mutex_session);
#endif

    while (session->dcc_sessions)
        libirc_remove_dcc_session(session, session->dcc_sessions, 0);

    free_line_parser(session->line_parser);
    fdwatch_free();

#ifdef ENABLE_SSL
    if (session->ssl)
        SSL_free(session->ssl);
#endif

    free(session);
}
예제 #6
0
static void libirc_dcc_add_descriptors (irc_session_t * ircsession, fd_set *in_set, fd_set *out_set, int * maxfd)
{
	irc_dcc_session_t * dcc, *dcc_next;
	time_t now = time (0);

	libirc_mutex_lock (&ircsession->mutex_dcc);

	// Preprocessing DCC list:
	// - ask DCC send callbacks for data;
	// - remove unused DCC structures
	for ( dcc = ircsession->dcc_sessions; dcc; dcc = dcc_next )
	{
		dcc_next = dcc->next;

		// Remove timed-out sessions
		if ( (dcc->state == LIBIRC_STATE_CONNECTING
			|| dcc->state == LIBIRC_STATE_INIT
			|| dcc->state == LIBIRC_STATE_LISTENING)
		&& now - dcc->timeout > ircsession->dcc_timeout )
		{
			// Inform the caller about DCC timeout.
			// Do not inform when state is LIBIRC_STATE_INIT - session
			// was initiated from someone else, and callbacks aren't set yet.
			if ( dcc->state != LIBIRC_STATE_INIT )
			{
				libirc_mutex_unlock (&ircsession->mutex_dcc);

				if ( dcc->cb )
					(*dcc->cb)(ircsession, dcc->id, LIBIRC_ERR_TIMEOUT, dcc->ctx, 0, 0);

				libirc_mutex_lock (&ircsession->mutex_dcc);
			}

			libirc_remove_dcc_session (ircsession, dcc, 0);
		}

		/*
		 * If we're sending file, and the output buffer is empty, we need
         * to provide some data.
         */
		if ( dcc->state == LIBIRC_STATE_CONNECTED
		&& dcc->dccmode == LIBIRC_DCC_SENDFILE
		&& dcc->dccsend_file_fp
		&& dcc->outgoing_offset == 0 )
		{
			int len = fread (dcc->outgoing_buf, 1, sizeof (dcc->outgoing_buf), dcc->dccsend_file_fp);

			if ( len <= 0 )
			{
				int err = (len < 0 ? LIBIRC_ERR_READ : 0);
			
				libirc_mutex_unlock (&ircsession->mutex_dcc);

				(*dcc->cb)(ircsession, dcc->id, err, dcc->ctx, 0, 0);
				libirc_mutex_lock (&ircsession->mutex_dcc);
				libirc_dcc_destroy_nolock (ircsession, dcc->id);
			}
			else
				dcc->outgoing_offset = len;
		}

		// Clean up unused sessions
		if ( dcc->state == LIBIRC_STATE_REMOVED )
			libirc_remove_dcc_session (ircsession, dcc, 0);
	}

	for ( dcc = ircsession->dcc_sessions; dcc; dcc = dcc->next )
	{
		switch (dcc->state)
		{
		case LIBIRC_STATE_LISTENING:
			// While listening, only in_set descriptor should be set
			libirc_add_to_set (dcc->sock, in_set, maxfd);
			break;

		case LIBIRC_STATE_CONNECTING:
			// While connection, only out_set descriptor should be set
			libirc_add_to_set (dcc->sock, out_set, maxfd);
			break;

		case LIBIRC_STATE_CONNECTED:
			// Add input descriptor if there is space in input buffer
			// and it is DCC chat (during DCC send, there is nothing to recv)
			if ( dcc->incoming_offset < sizeof(dcc->incoming_buf) - 1 )
				libirc_add_to_set (dcc->sock, in_set, maxfd);

			// Add output descriptor if there is something in output buffer
			libirc_mutex_lock (&dcc->mutex_outbuf);

			if ( dcc->outgoing_offset > 0  )
				libirc_add_to_set (dcc->sock, out_set, maxfd);

			libirc_mutex_unlock (&dcc->mutex_outbuf);
			break;

		case LIBIRC_STATE_CONFIRM_SIZE:
			/*
			 * If we're receiving file, then WE should confirm the transferred
             * part (so we have to sent data). But if we're sending the file, 
             * then RECEIVER should confirm the packet, so we have to receive
             * data.
             *
             * We don't need to LOCK_DCC_OUTBUF - during file transfer, buffers
             * can't change asynchronously.
             */
             if ( dcc->dccmode == LIBIRC_DCC_RECVFILE && dcc->outgoing_offset > 0 )
             	libirc_add_to_set (dcc->sock, out_set, maxfd);

             if ( dcc->dccmode == LIBIRC_DCC_SENDFILE && dcc->incoming_offset < 4 )
				libirc_add_to_set (dcc->sock, in_set, maxfd);

             break;
		}
	}

	libirc_mutex_unlock (&ircsession->mutex_dcc);
}
예제 #7
0
int	irc_dcc_sendfile (irc_session_t * session, void * ctx, const char * nick, const char * filename, irc_dcc_callback_t callback, irc_dcc_t * dccid)
{
	struct sockaddr_in saddr;
	socklen_t len = sizeof(saddr);
	char cmdbuf[128], notbuf[128];
	irc_dcc_session_t * dcc;
	const char * p;
	int err;
	long filesize;

	if ( !session || !dccid || !filename || !callback )
	{
		session->lasterror = LIBIRC_ERR_INVAL;
		return 1;
	}

	if ( session->state != LIBIRC_STATE_CONNECTED )
	{
		session->lasterror = LIBIRC_ERR_STATE;
		return 1;
	}

	if ( (err = libirc_new_dcc_session (session, 0, 0, LIBIRC_DCC_SENDFILE, ctx, &dcc)) != 0 )
	{
		session->lasterror = err;
		return 1;
	}

	if ( (dcc->dccsend_file_fp = fopen (filename, "rb")) == 0 )
	{
		libirc_remove_dcc_session (session, dcc, 1);
		session->lasterror = LIBIRC_ERR_OPENFILE;
		return 1;
	}

	/* Get file length */
	if ( fseek (dcc->dccsend_file_fp, 0, SEEK_END)
	|| (filesize = ftell (dcc->dccsend_file_fp)) == -1
	|| fseek (dcc->dccsend_file_fp, 0, SEEK_SET) )
	{
		libirc_remove_dcc_session (session, dcc, 1);
		session->lasterror = LIBIRC_ERR_NODCCSEND;
		return 1;
	}

	if ( getsockname (dcc->sock, (struct sockaddr*) &saddr, &len) < 0 )
	{
		libirc_remove_dcc_session (session, dcc, 1);
		session->lasterror = LIBIRC_ERR_SOCKET;
		return 1;
	}

	// Remove path from the filename
	if ( (p = strrchr (filename, '\\')) == 0
	&& (p = strrchr (filename, '/')) == 0 )
		p = filename;
	else
		p++; // skip directory slash

	sprintf (notbuf, "DCC Send %s (%s)", p, inet_ntoa (saddr.sin_addr));
	sprintf (cmdbuf, "DCC SEND %s %lu %u %ld", p, (unsigned long) ntohl (saddr.sin_addr.s_addr), ntohs (saddr.sin_port), filesize);

	if ( irc_cmd_notice (session, nick, notbuf)
	|| irc_cmd_ctcp_request (session, nick, cmdbuf) )
	{
		libirc_remove_dcc_session (session, dcc, 1);
		return 1;
	}

	*dccid = dcc->id;
	dcc->cb = callback;

	return 0;
}