Exemplo n.º 1
0
/* This one is actually pretty simple... Might get more calls if we can't write 
   the whole request at once. */
static gboolean http_connected( gpointer data, int source, b_input_condition cond )
{
	struct http_request *req = data;
	int st;
	
	if( source < 0 )
		goto error;
	
	if( req->inpa > 0 )
		b_event_remove( req->inpa );
	
	sock_make_nonblocking( req->fd );
	
	if( req->ssl )
	{
		st = ssl_write( req->ssl, req->request + req->bytes_written,
		                req->request_length - req->bytes_written );
		if( st < 0 )
		{
			if( ssl_errno != SSL_AGAIN )
			{
				ssl_disconnect( req->ssl );
				goto error;
			}
		}
	}
	else
	{
		st = write( source, req->request + req->bytes_written,
		                    req->request_length - req->bytes_written );
		if( st < 0 )
		{
			if( !sockerr_again() )
			{
				closesocket( req->fd );
				goto error;
			}
		}
	}
	
	if( st > 0 )
		req->bytes_written += st;
	
	if( req->bytes_written < req->request_length )
		req->inpa = b_input_add( source,
		                         req->ssl ? ssl_getdirection( req->ssl ) : B_EV_IO_WRITE,
	        	                 http_connected, req );
	else
		req->inpa = b_input_add( source, B_EV_IO_READ, http_incoming_data, req );
	
	return FALSE;
	
error:
	if( req->status_string == NULL )
		req->status_string = g_strdup( "Error while writing HTTP request" );
	
	req->func( req );
	http_free( req );
	return FALSE;
}
Exemplo n.º 2
0
static void s5_sendconnect(gpointer data, gint source)
{
	unsigned char buf[512];
	struct PHB *phb = data;
	int hlen = strlen(phb->host);
	
	buf[0] = 0x05;
	buf[1] = 0x01;		/* CONNECT */
	buf[2] = 0x00;		/* reserved */
	buf[3] = 0x03;		/* address type -- host name */
	buf[4] = hlen;
	memcpy(buf + 5, phb->host, hlen);
	buf[5 + strlen(phb->host)] = phb->port >> 8;
	buf[5 + strlen(phb->host) + 1] = phb->port & 0xff;

	if (write(source, buf, (5 + strlen(phb->host) + 2)) < (5 + strlen(phb->host) + 2)) {
		close(source);
		phb->func(phb->data, -1, GAIM_INPUT_READ);
		g_free(phb->host);
		g_free(phb);
		return;
	}

	phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_canread_again, phb);
}
Exemplo n.º 3
0
static gboolean s5_canread(gpointer data, gint source, b_input_condition cond)
{
	unsigned char buf[512];
	struct PHB *phb = data;

	b_event_remove(phb->inpa);

	if (read(source, buf, 2) < 2) {
		return phb_free(phb, FALSE);
	}

	if ((buf[0] != 0x05) || (buf[1] == 0xff)) {
		return phb_free(phb, FALSE);
	}

	if (buf[1] == 0x02) {
		unsigned int i = strlen(proxyuser), j = strlen(proxypass);
		buf[0] = 0x01;  /* version 1 */
		buf[1] = i;
		memcpy(buf + 2, proxyuser, i);
		buf[2 + i] = j;
		memcpy(buf + 2 + i + 1, proxypass, j);
		if (write(source, buf, 3 + i + j) < 3 + i + j) {
			return phb_free(phb, FALSE);
		}

		phb->inpa = b_input_add(source, B_EV_IO_READ, s5_readauth, phb);
	} else {
		s5_sendconnect(phb, source);
	}

	return FALSE;
}
Exemplo n.º 4
0
gboolean
Skype_begin (im_connection* connection)
{
    SkypeData* skype = connection->proto_data;
    int        result;

    if (!skype) {
        return FALSE;
    }

    skype->bfd = b_input_add(skype->fd, B_EV_IO_READ, Skype_loop, connection);

    /* Identifying */
    Skype_printf(connection, "USERNAME %s\n", connection->acc->user);
    Skype_printf(connection, "PASSWORD %s\n", connection->acc->pass);

    result = Skype_printf(connection, "SEARCH FRIENDS\n");

    Skype_printf(connection, "SET USERSTATUS ONLINE\n");

    if (set_getbool(&connection->acc->set, "auto_join")) {
        Skype_printf(connection, "SEARCH BOOKMRKEDCHATS\n");
    }

    return result;
}
Exemplo n.º 5
0
static gboolean http_canwrite(gpointer data, gint source, b_input_condition cond)
{
	char cmd[384];
	struct PHB *phb = data;
	unsigned int len;
	int error = ETIMEDOUT;
	if (phb->inpa > 0)
		b_event_remove(phb->inpa);
	len = sizeof(error);
	if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
		close(source);
		phb->func(phb->data, -1, GAIM_INPUT_READ);
		g_free(phb->host);
		g_free(phb);
		return FALSE;
	}
	sock_make_blocking(source);

	g_snprintf(cmd, sizeof(cmd), "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n", phb->host, phb->port,
		   phb->host, phb->port);
	if (send(source, cmd, strlen(cmd), 0) < 0) {
		close(source);
		phb->func(phb->data, -1, GAIM_INPUT_READ);
		g_free(phb->host);
		g_free(phb);
		return FALSE;
	}

	if (strlen(proxyuser) > 0) {
		char *t1, *t2;
		t1 = g_strdup_printf("%s:%s", proxyuser, proxypass);
		t2 = tobase64(t1);
		g_free(t1);
		g_snprintf(cmd, sizeof(cmd), "Proxy-Authorization: Basic %s\r\n", t2);
		g_free(t2);
		if (send(source, cmd, strlen(cmd), 0) < 0) {
			close(source);
			phb->func(phb->data, -1, GAIM_INPUT_READ);
			g_free(phb->host);
			g_free(phb);
			return FALSE;
		}
	}

	g_snprintf(cmd, sizeof(cmd), "\r\n");
	if (send(source, cmd, strlen(cmd), 0) < 0) {
		close(source);
		phb->func(phb->data, -1, GAIM_INPUT_READ);
		g_free(phb->host);
		g_free(phb);
		return FALSE;
	}

	phb->inpa = b_input_add(source, GAIM_INPUT_READ, http_canread, phb);
	
	return FALSE;
}
Exemplo n.º 6
0
static gboolean s4_canwrite(gpointer data, gint source, b_input_condition cond)
{
	unsigned char packet[12];
	struct hostent *hp;
	struct PHB *phb = data;
	socklen_t len;
	int error = ETIMEDOUT;
	gboolean is_socks4a = (proxytype == PROXY_SOCKS4A);

	if (phb->inpa > 0) {
		b_event_remove(phb->inpa);
	}
	len = sizeof(error);
	if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
		return phb_free(phb, FALSE);
	}
	sock_make_blocking(source);

	if (!is_socks4a && !(hp = gethostbyname(phb->host))) {
		return phb_free(phb, FALSE);
	}

	packet[0] = 4;
	packet[1] = 1;
	packet[2] = phb->port >> 8;
	packet[3] = phb->port & 0xff;
	if (is_socks4a) {
		packet[4] = 0;
		packet[5] = 0;
		packet[6] = 0;
		packet[7] = 1;
	} else {
		packet[4] = (unsigned char) (hp->h_addr_list[0])[0];
		packet[5] = (unsigned char) (hp->h_addr_list[0])[1];
		packet[6] = (unsigned char) (hp->h_addr_list[0])[2];
		packet[7] = (unsigned char) (hp->h_addr_list[0])[3];
	}
	packet[8] = 0;
	if (write(source, packet, 9) != 9) {
		return phb_free(phb, FALSE);
	}

	if (is_socks4a) {
		size_t host_len = strlen(phb->host) + 1; /* include the \0 */

		if (write(source, phb->host, host_len) != host_len) {
			return phb_free(phb, FALSE);
		}
	}

	phb->inpa = b_input_add(source, B_EV_IO_READ, s4_canread, phb);

	return FALSE;
}
Exemplo n.º 7
0
static gboolean s4_canwrite(gpointer data, gint source, b_input_condition cond)
{
	unsigned char packet[12];
	struct hostent *hp;
	struct PHB *phb = data;
	unsigned int len;
	int error = ETIMEDOUT;
	if (phb->inpa > 0)
		b_event_remove(phb->inpa);
	len = sizeof(error);
	if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
		close(source);
		phb->func(phb->data, -1, GAIM_INPUT_READ);
		g_free(phb->host);
		g_free(phb);
		return FALSE;
	}
	sock_make_blocking(source);

	/* XXX does socks4 not support host name lookups by the proxy? */
	if (!(hp = gethostbyname(phb->host))) {
		close(source);
		phb->func(phb->data, -1, GAIM_INPUT_READ);
		g_free(phb->host);
		g_free(phb);
		return FALSE;
	}

	packet[0] = 4;
	packet[1] = 1;
	packet[2] = phb->port >> 8;
	packet[3] = phb->port & 0xff;
	packet[4] = (unsigned char)(hp->h_addr_list[0])[0];
	packet[5] = (unsigned char)(hp->h_addr_list[0])[1];
	packet[6] = (unsigned char)(hp->h_addr_list[0])[2];
	packet[7] = (unsigned char)(hp->h_addr_list[0])[3];
	packet[8] = 0;
	if (write(source, packet, 9) != 9) {
		close(source);
		phb->func(phb->data, -1, GAIM_INPUT_READ);
		g_free(phb->host);
		g_free(phb);
		return FALSE;
	}

	phb->inpa = b_input_add(source, GAIM_INPUT_READ, s4_canread, phb);
	
	return FALSE;
}
Exemplo n.º 8
0
static gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond )
{
	struct msn_handler_data *handler = data;
	struct im_connection *ic = handler->data;
	struct msn_data *md;
	
	if( !g_slist_find( msn_connections, ic ) )
		return FALSE;
	
	md = ic->proto_data;
	
	if( source == -1 )
	{
		imcb_error( ic, "Could not connect to server" );
		imc_logout( ic, TRUE );
		return FALSE;
	}
	
	g_free( handler->rxq );
	handler->rxlen = 0;
	handler->rxq = g_new0( char, 1 );
	
	if( md->uuid == NULL )
	{
		struct utsname name;
		sha1_state_t sha[1];
		
		/* UUID == SHA1("BitlBee" + my hostname + MSN username) */
		sha1_init( sha );
		sha1_append( sha, (void*) "BitlBee", 7 );
		if( uname( &name ) == 0 )
		{
			sha1_append( sha, (void*) name.nodename, strlen( name.nodename ) );
		}
		sha1_append( sha, (void*) ic->acc->user, strlen( ic->acc->user ) );
		md->uuid = sha1_random_uuid( sha );
		memcpy( md->uuid, "b171be3e", 8 ); /* :-P */
	}
	
	if( msn_ns_write( ic, source, "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER ) )
	{
		handler->inpa = b_input_add( handler->fd, B_EV_IO_READ, msn_ns_callback, handler );
		imcb_log( ic, "Connected to server, waiting for reply" );
	}
	
	return FALSE;
}
Exemplo n.º 9
0
int ipc_master_load_state( char *statefile )
{
	struct bitlbee_child *child;
	FILE *fp;
	int i, n;
	
	if( statefile == NULL )
		return 0;
	
	fp = fopen( statefile, "r" );
	unlink( statefile );	/* Why do it later? :-) */
	if( fp == NULL )
		return 0;
	
	if( fscanf( fp, "%d", &n ) != 1 )
	{
		log_message( LOGLVL_WARNING, "Could not import state information for child processes." );
		fclose( fp );
		return 0;
	}
	
	log_message( LOGLVL_INFO, "Importing information for %d child processes.", n );
	for( i = 0; i < n; i ++ )
	{
		child = g_new0( struct bitlbee_child, 1 );
		
		if( fscanf( fp, "%d %d", (int *) &child->pid, &child->ipc_fd ) != 2 )
		{
			log_message( LOGLVL_WARNING, "Unexpected end of file: Only processed %d clients.", i );
			g_free( child );
			fclose( fp );
			return 0;
		}
		child->ipc_inpa = b_input_add( child->ipc_fd, B_EV_IO_READ, ipc_master_read, child );
		child->to_fd = -1;
		
		child_list = g_slist_prepend( child_list, child );
	}
	
	ipc_to_children_str( "HELLO\r\n" );
	ipc_to_children_str( "OPERMSG :New %s master process started (version %s)\r\n", PACKAGE, BITLBEE_VERSION );
	
	fclose( fp );
	return 1;
}
Exemplo n.º 10
0
static gboolean gaim_io_connected(gpointer data, gint source, b_input_condition cond)
{
	struct PHB *phb = data;
	socklen_t len;
	int error = ETIMEDOUT;
	len = sizeof(error);
	
	if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0 || error) {
		if ((phb->gai_cur = phb->gai_cur->ai_next)) {
			int new_fd;
			b_event_remove(phb->inpa);
			if ((new_fd = proxy_connect_none(NULL, 0, phb))) {
				b_event_remove(phb->inpa);
				closesocket(source);
				dup2(new_fd, source);
				closesocket(new_fd);
				phb->inpa = b_input_add(source, B_EV_IO_WRITE, gaim_io_connected, phb);
				return FALSE;
			}
		}
		freeaddrinfo(phb->gai);
		closesocket(source);
		b_event_remove(phb->inpa);
		phb->inpa = 0;
		if( phb->proxy_func )
			phb->proxy_func(phb->proxy_data, -1, B_EV_IO_READ);
		else {
			phb->func(phb->data, -1, B_EV_IO_READ);
			g_free(phb);
		}
		return FALSE;
	}
	freeaddrinfo(phb->gai);
	sock_make_blocking(source);
	b_event_remove(phb->inpa);
	phb->inpa = 0;
	if( phb->proxy_func )
		phb->proxy_func(phb->proxy_data, source, B_EV_IO_READ);
	else {
		phb->func(phb->data, source, B_EV_IO_READ);
		g_free(phb);
	}
	
	return FALSE;
}
Exemplo n.º 11
0
static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond )
{
	struct scd *conn = data;
	int st, stver;
	
	if( ( st = gnutls_handshake( conn->session ) ) < 0 )
	{
		if( st == GNUTLS_E_AGAIN || st == GNUTLS_E_INTERRUPTED )
		{
			conn->inpa = b_input_add( conn->fd, ssl_getdirection( conn ),
			                          ssl_handshake, data );
		}
		else
		{
			conn->func( conn->data, 0, NULL, cond );
			
			gnutls_deinit( conn->session );
			closesocket( conn->fd );
			
			g_free( conn );
		}
	}
	else
	{
		if( conn->verify && ( stver = verify_certificate_callback( conn->session ) ) != 0 )
		{
			conn->func( conn->data, stver, NULL, cond );

			gnutls_deinit( conn->session );
			closesocket( conn->fd );

			g_free( conn );
		}
		else
		{
			/* For now we can't handle non-blocking perfectly everywhere... */
			sock_make_blocking( conn->fd );
		
			conn->established = TRUE;
			conn->func( conn->data, 0, conn, cond );
		}
	}
	
	return FALSE;
}
Exemplo n.º 12
0
static gboolean new_ipc_client( gpointer data, gint serversock, b_input_condition cond )
{
	struct bitlbee_child *child = g_new0( struct bitlbee_child, 1 );
	
	child->to_fd = -1;
	child->ipc_fd = accept( serversock, NULL, 0 );
	if( child->ipc_fd == -1 )
	{
		log_message( LOGLVL_WARNING, "Unable to accept connection on UNIX domain socket: %s", strerror(errno) );
		return TRUE;
	}
		
	child->ipc_inpa = b_input_add( child->ipc_fd, B_EV_IO_READ, ipc_master_read, child );
	
	child_list = g_slist_prepend( child_list, child );
	
	return TRUE;
}
Exemplo n.º 13
0
/**
 * Implemented #ssl_input_function for the connection of #fb_mqtt->ssl.
 *
 * @param data  The user defined data, which is #fb_mqtt.
 * @param error The SSL error. (0 on success)
 * @param ssl   The SSL source.
 * @param cond  The #b_input_condition.
 *
 * @return TRUE for continued event handling, otherwise FALSE.
 **/
static gboolean fb_mqtt_cb_open(gpointer data, gint error, gpointer ssl,
                                b_input_condition cond)
{
    fb_mqtt_t *mqtt = data;
    gint       fd;

    if ((ssl == NULL) || (error != SSL_OK)) {
        fb_mqtt_error(mqtt, FB_MQTT_ERROR_GENERAL, "Failed to connect");
        return FALSE;
    }

    fb_mqtt_timeout_clear(mqtt);
    fd = ssl_getfd(mqtt->ssl);
    mqtt->rev = b_input_add(fd, B_EV_IO_READ, fb_mqtt_cb_read, mqtt);

    FB_MQTT_FUNC(mqtt, open);
    return FALSE;
}
Exemplo n.º 14
0
static gboolean s5_canwrite(gpointer data, gint source, b_input_condition cond)
{
	unsigned char buf[512];
	int i;
	struct PHB *phb = data;
	unsigned int len;
	int error = ETIMEDOUT;
	if (phb->inpa > 0)
		b_event_remove(phb->inpa);
	len = sizeof(error);
	if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
		close(source);
		phb->func(phb->data, -1, GAIM_INPUT_READ);
		g_free(phb->host);
		g_free(phb);
		return FALSE;
	}
	sock_make_blocking(source);

	i = 0;
	buf[0] = 0x05;		/* SOCKS version 5 */
	if (proxyuser[0]) {
		buf[1] = 0x02;	/* two methods */
		buf[2] = 0x00;	/* no authentication */
		buf[3] = 0x02;	/* username/password authentication */
		i = 4;
	} else {
		buf[1] = 0x01;
		buf[2] = 0x00;
		i = 3;
	}

	if (write(source, buf, i) < i) {
		close(source);
		phb->func(phb->data, -1, GAIM_INPUT_READ);
		g_free(phb->host);
		g_free(phb);
		return FALSE;
	}

	phb->inpa = b_input_add(source, GAIM_INPUT_READ, s5_canread, phb);
	
	return FALSE;
}
Exemplo n.º 15
0
int jabber_write( struct im_connection *ic, char *buf, int len )
{
	struct jabber_data *jd = ic->proto_data;
	gboolean ret;
	
	if( jd->flags & JFLAG_XMLCONSOLE )
	{
		char *msg;
		
		msg = g_strdup_printf( "TX: %s", buf );
		imcb_buddy_msg( ic, JABBER_XMLCONSOLE_HANDLE, msg, 0, 0 );
		g_free( msg );
	}
	
	if( jd->tx_len == 0 )
	{
		/* If the queue is empty, allocate a new buffer. */
		jd->tx_len = len;
		jd->txq = g_memdup( buf, len );
		
		/* Try if we can write it immediately so we don't have to do
		   it via the event handler. If not, add the handler. (In
		   most cases it probably won't be necessary.) */
		if( ( ret = jabber_write_queue( ic ) ) && jd->tx_len > 0 )
			jd->w_inpa = b_input_add( jd->fd, GAIM_INPUT_WRITE, jabber_write_callback, ic );
	}
	else
	{
		/* Just add it to the buffer if it's already filled. The
		   event handler is already set. */
		jd->txq = g_renew( char, jd->txq, jd->tx_len + len );
		memcpy( jd->txq + jd->tx_len, buf, len );
		jd->tx_len += len;
		
		/* The return value for write() doesn't necessarily mean
		   that everything got sent, it mainly means that the
		   connection (officially) still exists and can still
		   be accessed without hitting SIGSEGV. IOW: */
		ret = TRUE;
	}
	
	return ret;
}
Exemplo n.º 16
0
static int proxy_connect_none(const char *host, unsigned short port, struct PHB *phb)
{
	struct sockaddr_in *sin;
	struct sockaddr_in me;
	int fd = -1;

	if (!(sin = gaim_gethostbyname(host, port))) {
		g_free(phb);
		return -1;
	}

	if ((fd = socket(sin->sin_family, SOCK_STREAM, 0)) < 0) {
		g_free(phb);
		return -1;
	}

	sock_make_nonblocking(fd);
	
	if( global.conf->iface_out )
	{
		me.sin_family = AF_INET;
		me.sin_port = 0;
		me.sin_addr.s_addr = inet_addr( global.conf->iface_out );
		
		if( bind( fd, (struct sockaddr *) &me, sizeof( me ) ) != 0 )
			event_debug( "bind( %d, \"%s\" ) failure\n", fd, global.conf->iface_out );
	}
	
	event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port, fd);
	
	if (connect(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0 && !sockerr_again()) {
		closesocket(fd);
		g_free(phb);
		
		return -1;
	} else {
		phb->inpa = b_input_add(fd, GAIM_INPUT_WRITE, gaim_io_connected, phb);
		phb->fd = fd;
		
		return fd;
	}
}
Exemplo n.º 17
0
static gboolean ssl_handshake(gpointer data, gint source, b_input_condition cond)
{
    struct scd *conn = data;
    int st;

    if ((st = SSL_connect(conn->ssl)) < 0) {
        conn->lasterr = SSL_get_error(conn->ssl, st);
        if (conn->lasterr != SSL_ERROR_WANT_READ && conn->lasterr != SSL_ERROR_WANT_WRITE) {
            conn->func(conn->data, 0, NULL, cond);
            ssl_disconnect(conn);
            return FALSE;
        }

        conn->inpa = b_input_add(conn->fd, ssl_getdirection(conn), ssl_handshake, data);
        return FALSE;
    }

    conn->established = TRUE;
    sock_make_blocking(conn->fd);           /* For now... */
    conn->func(conn->data, 0, conn, cond);
    return FALSE;
}
Exemplo n.º 18
0
int ipc_master_listen_socket()
{
	struct sockaddr_un un_addr;
	int serversock;

	if (!IPCSOCKET || !*IPCSOCKET)
		return 1;

	/* Clean up old socket files that were hanging around.. */
	if (unlink(IPCSOCKET) == -1 && errno != ENOENT) {
		log_message( LOGLVL_ERROR, "Could not remove old IPC socket at %s: %s", IPCSOCKET, strerror(errno) );
		return 0;
	}

	un_addr.sun_family = AF_UNIX;
	strcpy(un_addr.sun_path, IPCSOCKET);

	serversock = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);

	if (serversock == -1) {
		log_message( LOGLVL_WARNING, "Unable to create UNIX socket: %s", strerror(errno) );
		return 0;
	}

	if (bind(serversock, (struct sockaddr *)&un_addr, sizeof(un_addr)) == -1) {
		log_message( LOGLVL_WARNING, "Unable to bind UNIX socket to %s: %s", IPCSOCKET, strerror(errno) );
		return 0;
	}

	if (listen(serversock, 5) == -1) {
		log_message( LOGLVL_WARNING, "Unable to listen on UNIX socket: %s", strerror(errno) );
		return 0;
	}
	
	b_input_add( serversock, B_EV_IO_READ, new_ipc_client, NULL );
	
	return 1;
}
Exemplo n.º 19
0
/**
 * Writes a #fb_mqtt_msg to the #fb_mqtt.
 *
 * @param mqtt The #fb_mqtt.
 * @param msg  The #fb_mqtt_msg.
 **/
void fb_mqtt_write(fb_mqtt_t *mqtt, fb_mqtt_msg_t *msg)
{
    const GByteArray *bytes;
    gint fd;

    g_return_if_fail(mqtt != NULL);

    bytes = fb_mqtt_msg_bytes(msg);

    if (G_UNLIKELY(bytes == NULL)) {
        fb_mqtt_error(mqtt, FB_MQTT_ERROR_GENERAL, "Failed to format data");
        return;
    }

    fb_util_hexdump(bytes, 2, "Writing %d (flags: 0x%0X)",
                    msg->type, msg->flags);

    fd = ssl_getfd(mqtt->ssl);
    g_byte_array_append(mqtt->wbuf, bytes->data, bytes->len);

    if ((mqtt->wev < 1) && fb_mqtt_cb_write(mqtt, fd, B_EV_IO_WRITE))
        mqtt->wev = b_input_add(fd, B_EV_IO_WRITE, fb_mqtt_cb_write, mqtt);
}
Exemplo n.º 20
0
gboolean jabber_start_stream( struct im_connection *ic )
{
	struct jabber_data *jd = ic->proto_data;
	int st;
	char *greet;
	
	/* We'll start our stream now, so prepare everything to receive one
	   from the server too. */
	xt_free( jd->xt );	/* In case we're RE-starting. */
	jd->xt = xt_new( jabber_handlers, ic );
	
	if( jd->r_inpa <= 0 )
		jd->r_inpa = b_input_add( jd->fd, GAIM_INPUT_READ, jabber_read_callback, ic );
	
	greet = g_strdup_printf( "<?xml version='1.0' ?>"
	                         "<stream:stream to=\"%s\" xmlns=\"jabber:client\" "
	                          "xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">", jd->server );
	
	st = jabber_write( ic, greet, strlen( greet ) );
	
	g_free( greet );
	
	return st;
}
Exemplo n.º 21
0
Arquivo: irc.c Projeto: dgruss/bitlbee
irc_t *irc_new(int fd)
{
	irc_t *irc;
	struct sockaddr_storage sock;
	socklen_t socklen = sizeof(sock);
	char *host = NULL, *myhost = NULL;
	irc_user_t *iu;
	GSList *l;
	set_t *s;
	bee_t *b;

	irc = g_new0(irc_t, 1);

	irc->fd = fd;
	sock_make_nonblocking(irc->fd);

	irc->r_watch_source_id = b_input_add(irc->fd, B_EV_IO_READ, bitlbee_io_current_client_read, irc);

	irc->status = USTATUS_OFFLINE;
	irc->last_pong = gettime();

	irc->nick_user_hash = g_hash_table_new(g_str_hash, g_str_equal);
	irc->watches = g_hash_table_new(g_str_hash, g_str_equal);

	irc->iconv = (GIConv) - 1;
	irc->oconv = (GIConv) - 1;

	if (global.conf->hostname) {
		myhost = g_strdup(global.conf->hostname);
	} else if (getsockname(irc->fd, (struct sockaddr*) &sock, &socklen) == 0) {
		char buf[NI_MAXHOST + 1];

		if (getnameinfo((struct sockaddr *) &sock, socklen, buf,
		                NI_MAXHOST, NULL, 0, 0) == 0) {
			myhost = g_strdup(ipv6_unwrap(buf));
		}
	}

	if (getpeername(irc->fd, (struct sockaddr*) &sock, &socklen) == 0) {
		char buf[NI_MAXHOST + 1];

		if (getnameinfo((struct sockaddr *) &sock, socklen, buf,
		                NI_MAXHOST, NULL, 0, 0) == 0) {
			host = g_strdup(ipv6_unwrap(buf));
		}
	}

	if (host == NULL) {
		host = g_strdup("localhost.localdomain");
	}
	if (myhost == NULL) {
		myhost = g_strdup("localhost.localdomain");
	}

	if (global.conf->ping_interval > 0 && global.conf->ping_timeout > 0) {
		irc->ping_source_id = b_timeout_add(global.conf->ping_interval * 1000, irc_userping, irc);
	}

	irc_connection_list = g_slist_append(irc_connection_list, irc);

	b = irc->b = bee_new();
	b->ui_data = irc;
	b->ui = &irc_ui_funcs;

	s = set_add(&b->set, "allow_takeover", "true", set_eval_bool, irc);
	s = set_add(&b->set, "away_devoice", "true", set_eval_bw_compat, irc);
	s->flags |= SET_HIDDEN;
	s = set_add(&b->set, "away_reply_timeout", "3600", set_eval_int, irc);
	s = set_add(&b->set, "charset", "utf-8", set_eval_charset, irc);
	s = set_add(&b->set, "default_target", "root", NULL, irc);
	s = set_add(&b->set, "display_namechanges", "false", set_eval_bool, irc);
	s = set_add(&b->set, "display_timestamps", "true", set_eval_bool, irc);
	s = set_add(&b->set, "handle_unknown", "add_channel", NULL, irc);
	s = set_add(&b->set, "last_version", "0", NULL, irc);
	s->flags |= SET_HIDDEN;
	s = set_add(&b->set, "nick_format", "%-@nick", NULL, irc);
	s = set_add(&b->set, "nick_lowercase", "false", set_eval_bool, irc);
	s = set_add(&b->set, "nick_underscores", "false", set_eval_bool, irc);
	s = set_add(&b->set, "offline_user_quits", "true", set_eval_bool, irc);
	s = set_add(&b->set, "ops", "both", set_eval_irc_channel_ops, irc);
	s = set_add(&b->set, "paste_buffer", "false", set_eval_bool, irc);
	s->old_key = g_strdup("buddy_sendbuffer");
	s = set_add(&b->set, "paste_buffer_delay", "200", set_eval_int, irc);
	s->old_key = g_strdup("buddy_sendbuffer_delay");
	s = set_add(&b->set, "password", NULL, set_eval_password, irc);
	s->flags |= SET_NULL_OK | SET_PASSWORD;
	s = set_add(&b->set, "private", "true", set_eval_bool, irc);
	s = set_add(&b->set, "query_order", "lifo", NULL, irc);
	s = set_add(&b->set, "root_nick", ROOT_NICK, set_eval_root_nick, irc);
	s->flags |= SET_HIDDEN;
	s = set_add(&b->set, "show_offline", "false", set_eval_bw_compat, irc);
	s->flags |= SET_HIDDEN;
	s = set_add(&b->set, "self_messages", "true", set_eval_self_messages, irc);
	s = set_add(&b->set, "simulate_netsplit", "true", set_eval_bool, irc);
	s = set_add(&b->set, "timezone", "local", set_eval_timezone, irc);
	s = set_add(&b->set, "to_char", ": ", set_eval_to_char, irc);
	s = set_add(&b->set, "typing_notice", "false", set_eval_bool, irc);
	s = set_add(&b->set, "utf8_nicks", "false", set_eval_utf8_nicks, irc);

	irc->root = iu = irc_user_new(irc, ROOT_NICK);
	iu->host = g_strdup(myhost);
	iu->fullname = g_strdup(ROOT_FN);
	iu->f = &irc_user_root_funcs;

	iu = irc_user_new(irc, NS_NICK);
	iu->host = g_strdup(myhost);
	iu->fullname = g_strdup(ROOT_FN);
	iu->f = &irc_user_root_funcs;

	irc->user = g_new0(irc_user_t, 1);
	irc->user->host = g_strdup(host);

	conf_loaddefaults(irc);

	/* Evaluator sets the iconv/oconv structures. */
	set_eval_charset(set_find(&b->set, "charset"), set_getstr(&b->set, "charset"));

	irc_write(irc, ":%s NOTICE * :%s", irc->root->host, "BitlBee-IRCd initialized, please go on");
	if (isatty(irc->fd)) {
		irc_write(irc, ":%s NOTICE * :%s", irc->root->host,
		          "If you read this, you most likely accidentally "
		          "started BitlBee in inetd mode on the command line. "
		          "You probably want to run it in (Fork)Daemon mode. "
		          "See doc/README for more information.");
	}

	g_free(myhost);
	g_free(host);

	/* libpurple doesn't like fork()s after initializing itself, so this
	   is the right moment to initialize it. */
#ifdef WITH_PURPLE
	nogaim_init();
#endif

	/* SSL library initialization also should be done after the fork, to
	   avoid shared CSPRNG state. This is required by NSS, which refuses to
	   work if a fork is detected */
	ssl_init();

	for (l = irc_plugins; l; l = l->next) {
		irc_plugin_t *p = l->data;
		if (p->irc_new) {
			p->irc_new(irc);
		}
	}

	return irc;
}
Exemplo n.º 22
0
static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond )
{
	struct http_request *req = data;
	char buffer[4096];
	int st;
	
	if( req->inpa > 0 )
	{
		b_event_remove( req->inpa );
		req->inpa = 0;
	}
	
	if( req->ssl )
	{
		st = ssl_read( req->ssl, buffer, sizeof( buffer ) );
		if( st < 0 )
		{
			if( ssl_errno != SSL_AGAIN )
			{
				/* goto cleanup; */
				
				/* YAY! We have to deal with crappy Microsoft
				   servers that LOVE to send invalid TLS
				   packets that abort connections! \o/ */
				
				goto eof;
			}
		}
		else if( st == 0 )
		{
			goto eof;
		}
	}
	else
	{
		st = read( req->fd, buffer, sizeof( buffer ) );
		if( st < 0 )
		{
			if( !sockerr_again() )
			{
				req->status_string = g_strdup( strerror( errno ) );
				goto cleanup;
			}
		}
		else if( st == 0 )
		{
			goto eof;
		}
	}
	
	if( st > 0 )
	{
		http_ret_t c;
		
		if( req->flags & HTTPC_CHUNKED )
			c = http_process_chunked_data( req, buffer, st );
		else
			c = http_process_data( req, buffer, st );
		
		if( c == CR_EOF )
			goto eof;
		else if( c == CR_ERROR || c == CR_ABORT )
			return FALSE;
	}
	
	if( req->content_length != -1 &&
	    req->body_size >= req->content_length )
		goto eof;
	
	if( ssl_pending( req->ssl ) )
		return http_incoming_data( data, source, cond );
	
	/* There will be more! */
	req->inpa = b_input_add( req->fd,
	                         req->ssl ? ssl_getdirection( req->ssl ) : B_EV_IO_READ,
	                         http_incoming_data, req );
	
	return FALSE;

eof:
	req->flags |= HTTPC_EOF;
	
	/* Maybe if the webserver is overloaded, or when there's bad SSL
	   support... */
	if( req->bytes_read == 0 )
	{
		req->status_string = g_strdup( "Empty HTTP reply" );
		goto cleanup;
	}

cleanup:
	/* Avoid g_source_remove warnings */
	req->inpa = 0;

	if( req->ssl )
		ssl_disconnect( req->ssl );
	else
		closesocket( req->fd );
	
	if( req->body_size < req->content_length )
	{
		req->status_code = -1;
		g_free( req->status_string );
		req->status_string = g_strdup( "Response truncated" );
	}
	
	if( getenv( "BITLBEE_DEBUG" ) && req )
		printf( "Finishing HTTP request with status: %s\n",
		        req->status_string ? req->status_string : "NULL" );
	
	req->func( req );
	http_free( req );
	return FALSE;
}
Exemplo n.º 23
0
static int proxy_connect_none(const char *host, unsigned short port_, struct PHB *phb)
{
	struct sockaddr_in me;
	int fd = -1;
	
	if (phb->gai_cur == NULL)
	{
		int ret;
		char port[6];
		struct addrinfo hints;
	
		g_snprintf(port, sizeof(port), "%d", port_);
	
		memset(&hints, 0, sizeof(struct addrinfo));
		hints.ai_family = AF_UNSPEC;
		hints.ai_socktype = SOCK_STREAM;
		hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
	
		if (!(ret = getaddrinfo(host, port, &hints, &phb->gai)))
			phb->gai_cur = phb->gai;
		else
			event_debug("gai(): %s\n", gai_strerror(ret));
	}
	
	for (; phb->gai_cur; phb->gai_cur = phb->gai_cur->ai_next)
	{
		if ((fd = socket(phb->gai_cur->ai_family, phb->gai_cur->ai_socktype, phb->gai_cur->ai_protocol)) < 0) {
			event_debug( "socket failed: %d\n", errno);
			continue;
		}

		sock_make_nonblocking(fd);

		if (global.conf->iface_out)
		{
			me.sin_family = AF_INET;
			me.sin_port = 0;
			me.sin_addr.s_addr = inet_addr( global.conf->iface_out );
				
			if (bind(fd, (struct sockaddr *) &me, sizeof(me)) != 0)
				event_debug("bind( %d, \"%s\" ) failure\n", fd, global.conf->iface_out);
		}

		event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port_, fd);
	
		if (connect(fd, phb->gai_cur->ai_addr, phb->gai_cur->ai_addrlen) < 0 && !sockerr_again()) {
			event_debug( "connect failed: %s\n", strerror(errno));
			closesocket(fd);
			fd = -1;
			continue;
		} else {
			phb->inpa = b_input_add(fd, B_EV_IO_WRITE, gaim_io_connected, phb);
			phb->fd = fd;
			
			break;
		}
	}
	
	if(fd < 0 && host)
		g_free(phb);

	return fd;
}
Exemplo n.º 24
0
static guint prplcb_ev_input_add( int fd, PurpleInputCondition cond, PurpleInputFunction func, gpointer udata )
{
	return b_input_add( fd, cond | B_EV_FLAG_FORCE_REPEAT, (b_event_handler) func, udata );
}
Exemplo n.º 25
0
static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond )
{
	struct http_request *req = data;
	int evil_server = 0;
	char buffer[2048];
	char *end1, *end2;
	int st;
	
	if( req->inpa > 0 )
		b_event_remove( req->inpa );
	
	if( req->ssl )
	{
		st = ssl_read( req->ssl, buffer, sizeof( buffer ) );
		if( st < 0 )
		{
			if( ssl_errno != SSL_AGAIN )
			{
				/* goto cleanup; */
				
				/* YAY! We have to deal with crappy Microsoft
				   servers that LOVE to send invalid TLS
				   packets that abort connections! \o/ */
				
				goto got_reply;
			}
		}
		else if( st == 0 )
		{
			goto got_reply;
		}
	}
	else
	{
		st = read( req->fd, buffer, sizeof( buffer ) );
		if( st < 0 )
		{
			if( !sockerr_again() )
			{
				req->status_string = g_strdup( strerror( errno ) );
				goto cleanup;
			}
		}
		else if( st == 0 )
		{
			goto got_reply;
		}
	}
	
	if( st > 0 )
	{
		req->reply_headers = g_realloc( req->reply_headers, req->bytes_read + st + 1 );
		memcpy( req->reply_headers + req->bytes_read, buffer, st );
		req->bytes_read += st;
	}
	
	/* There will be more! */
	req->inpa = b_input_add( req->fd,
	                         req->ssl ? ssl_getdirection( req->ssl ) : B_EV_IO_READ,
	                         http_incoming_data, req );
	
	if( ssl_pending( req->ssl ) )
		return http_incoming_data( data, source, cond );
	else
		return FALSE;

got_reply:
	/* Maybe if the webserver is overloaded, or when there's bad SSL
	   support... */
	if( req->bytes_read == 0 )
	{
		req->status_string = g_strdup( "Empty HTTP reply" );
		goto cleanup;
	}
	
	/* Zero termination is very convenient. */
	req->reply_headers[req->bytes_read] = 0;
	
	/* Find the separation between headers and body, and keep stupid
	   webservers in mind. */
	end1 = strstr( req->reply_headers, "\r\n\r\n" );
	end2 = strstr( req->reply_headers, "\n\n" );
	
	if( end2 && end2 < end1 )
	{
		end1 = end2 + 1;
		evil_server = 1;
	}
	else if( end1 )
	{
		end1 += 2;
	}
	else
	{
		req->status_string = g_strdup( "Malformed HTTP reply" );
		goto cleanup;
	}
	
	*end1 = 0;
	
	if( getenv( "BITLBEE_DEBUG" ) )
		printf( "HTTP response headers:\n%s\n", req->reply_headers );
	
	if( evil_server )
		req->reply_body = end1 + 1;
	else
		req->reply_body = end1 + 2;
	
	req->body_size = req->reply_headers + req->bytes_read - req->reply_body;
	
	if( ( end1 = strchr( req->reply_headers, ' ' ) ) != NULL )
	{
		if( sscanf( end1 + 1, "%d", &req->status_code ) != 1 )
		{
			req->status_string = g_strdup( "Can't parse status code" );
			req->status_code = -1;
		}
		else
		{
			char *eol;
			
			if( evil_server )
				eol = strchr( end1, '\n' );
			else
				eol = strchr( end1, '\r' );
			
			req->status_string = g_strndup( end1 + 1, eol - end1 - 1 );
			
			/* Just to be sure... */
			if( ( eol = strchr( req->status_string, '\r' ) ) )
				*eol = 0;
			if( ( eol = strchr( req->status_string, '\n' ) ) )
				*eol = 0;
		}
	}
	else
	{
		req->status_string = g_strdup( "Can't locate status code" );
		req->status_code = -1;
	}
	
	if( ( ( req->status_code >= 301 && req->status_code <= 303 ) ||
	      req->status_code == 307 ) && req->redir_ttl-- > 0 )
	{
		char *loc, *new_request, *new_host;
		int error = 0, new_port, new_proto;
		
		/* We might fill it again, so let's not leak any memory. */
		g_free( req->status_string );
		req->status_string = NULL;
		
		loc = strstr( req->reply_headers, "\nLocation: " );
		if( loc == NULL ) /* We can't handle this redirect... */
		{
			req->status_string = g_strdup( "Can't locate Location: header" );
			goto cleanup;
		}
		
		loc += 11;
		while( *loc == ' ' )
			loc ++;
		
		/* TODO/FIXME: Possibly have to handle relative redirections,
		   and rewrite Host: headers. Not necessary for now, it's
		   enough for passport authentication like this. */
		
		if( *loc == '/' )
		{
			/* Just a different pathname... */
			
			/* Since we don't cache the servername, and since we
			   don't need this yet anyway, I won't implement it. */
			
			req->status_string = g_strdup( "Can't handle recursive redirects" );
			
			goto cleanup;
		}
		else
		{
			/* A whole URL */
			url_t *url;
			char *s;
			const char *new_method;
			
			s = strstr( loc, "\r\n" );
			if( s == NULL )
				goto cleanup;
			
			url = g_new0( url_t, 1 );
			*s = 0;
			
			if( !url_set( url, loc ) )
			{
				req->status_string = g_strdup( "Malformed redirect URL" );
				g_free( url );
				goto cleanup;
			}
			
			/* Find all headers and, if necessary, the POST request contents.
			   Skip the old Host: header though. This crappy code here means
			   anything using this http_client MUST put the Host: header at
			   the top. */
			if( !( ( s = strstr( req->request, "\r\nHost: " ) ) &&
			       ( s = strstr( s + strlen( "\r\nHost: " ), "\r\n" ) ) ) )
			{
				req->status_string = g_strdup( "Error while rebuilding request string" );
				g_free( url );
				goto cleanup;
			}
			
			/* More or less HTTP/1.0 compliant, from my reading of RFC 2616.
			   Always perform a GET request unless we received a 301. 303 was
			   meant for this but it's HTTP/1.1-only and we're specifically
			   speaking HTTP/1.0. ...
			   
			   Well except someone at identi.ca's didn't bother reading any
			   RFCs and just return HTTP/1.1-specific status codes to HTTP/1.0
			   requests. Fuckers. So here we are, handle 301..303,307. */
			if( strncmp( req->request, "GET", 3 ) == 0 )
				/* GETs never become POSTs. */
				new_method = "GET";
			else if( req->status_code == 302 || req->status_code == 303 )
				/* 302 de-facto becomes GET, 303 as specified by RFC 2616#10.3.3 */
				new_method = "GET";
			else
				/* 301 de-facto should stay POST, 307 specifally RFC 2616#10.3.8 */
				new_method = "POST";
			
			/* Okay, this isn't fun! We have to rebuild the request... :-( */
			new_request = g_strdup_printf( "%s %s HTTP/1.0\r\nHost: %s%s",
			                               new_method, url->file, url->host, s );
			
			new_host = g_strdup( url->host );
			new_port = url->port;
			new_proto = url->proto;
			
			/* If we went from POST to GET, truncate the request content. */
			if( new_request[0] != req->request[0] && new_request[0] == 'G' &&
			    ( s = strstr( new_request, "\r\n\r\n" ) ) )
				s[4] = '\0';
			
			g_free( url );
		}
		
		if( req->ssl )
			ssl_disconnect( req->ssl );
		else
			closesocket( req->fd );
		
		req->fd = -1;
		req->ssl = NULL;
		
		if( getenv( "BITLBEE_DEBUG" ) )
			printf( "New headers for redirected HTTP request:\n%s\n", new_request );
	
		if( new_proto == PROTO_HTTPS )
		{
			req->ssl = ssl_connect( new_host, new_port, TRUE, http_ssl_connected, req );
			if( req->ssl == NULL )
				error = 1;
		}
		else
		{
			req->fd = proxy_connect( new_host, new_port, http_connected, req );
			if( req->fd < 0 )
				error = 1;
		}
		g_free( new_host );
		
		if( error )
		{
			req->status_string = g_strdup( "Connection problem during redirect" );
			g_free( new_request );
			goto cleanup;
		}
		
		g_free( req->request );
		g_free( req->reply_headers );
		req->request = new_request;
		req->request_length = strlen( new_request );
		req->bytes_read = req->bytes_written = req->inpa = 0;
		req->reply_headers = req->reply_body = NULL;
		
		return FALSE;
	}
	
	/* Assume that a closed connection means we're finished, this indeed
	   breaks with keep-alive connections and faulty connections. */
	req->finished = 1;

cleanup:
	if( req->ssl )
		ssl_disconnect( req->ssl );
	else
		closesocket( req->fd );
	
	if( getenv( "BITLBEE_DEBUG" ) && req )
		printf( "Finishing HTTP request with status: %s\n",
		        req->status_string ? req->status_string : "NULL" );
	
	req->func( req );
	http_free( req );
	return FALSE;
}
Exemplo n.º 26
0
static int
discord_ws_callback(struct lws *wsi,
                    enum lws_callback_reasons reason,
                    void *user, void *in, size_t len)
{
  struct im_connection *ic = NULL;
  discord_data *dd = NULL;

  if (wsi == NULL) {
    return 0;
  }

  struct lws_context *wsctx = lws_get_context(wsi);
  if (wsctx != NULL) {
    ic = lws_context_user(wsctx);
    dd = ic->proto_data;
  }

  switch(reason) {
    case LWS_CALLBACK_CLIENT_ESTABLISHED:
      dd->state = WS_CONNECTED;
      lws_callback_on_writable(wsi);
      break;
    case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
      imcb_error(ic, "Websocket connection error");
      if (in != NULL) {
        imcb_error(ic, in);
      }
      b_event_remove(dd->keepalive_loop_id);
      dd->keepalive_loop_id = 0;
      dd->state = WS_CLOSING;
      break;
    case LWS_CALLBACK_CLIENT_WRITEABLE:
      if (dd->state == WS_CONNECTED) {
        GString *buf = g_string_new("");
        g_string_printf(buf, "{\"d\":{\"v\":3,\"token\":\"%s\",\"properties\":{\"$referring_domain\":\"\",\"$browser\":\"bitlbee-discord\",\"$device\":\"bitlbee\",\"$referrer\":\"\",\"$os\":\"linux\"}},\"op\":2}", dd->token);
        discord_ws_send_payload(wsi, buf->str, buf->len);
        g_string_free(buf, TRUE);
      } else if (dd->state == WS_READY) {
        GString *buf = g_string_new("");

        g_string_printf(buf, "{\"op\":1,\"d\":%tu}", time(NULL));
        discord_ws_send_payload(dd->lws, buf->str, buf->len);
        g_string_free(buf, TRUE);
      } else {
        g_print("%s: Unhandled writable callback\n", __func__);
      }
      break;
    case LWS_CALLBACK_CLIENT_RECEIVE:
      {
        size_t rpload = lws_remaining_packet_payload(wsi);
        if (dd->ws_buf == NULL) {
          dd->ws_buf = g_string_new("");
        }
        dd->ws_buf = g_string_append(dd->ws_buf, in);
        if (rpload == 0) {
          discord_parse_message(ic);
          g_string_free(dd->ws_buf, TRUE);
          dd->ws_buf = NULL;
        }
        break;
      }
    case LWS_CALLBACK_CLOSED:
      b_event_remove(dd->keepalive_loop_id);
      dd->keepalive_loop_id = 0;
      dd->state = WS_CLOSING;
      lws_cancel_service(dd->lwsctx);
      break;
    case LWS_CALLBACK_ADD_POLL_FD:
      {
        struct lws_pollargs *pargs = in;
        dd->main_loop_id = b_input_add(pargs->fd, B_EV_IO_READ,
                                       discord_ws_service_loop, ic);
        break;
      }
    case LWS_CALLBACK_DEL_POLL_FD:
      b_event_remove(dd->main_loop_id);
      break;
    case LWS_CALLBACK_CHANGE_MODE_POLL_FD:
      {
        struct lws_pollargs *pargs = in;
        int flags = 0;
        b_event_remove(dd->main_loop_id);
        if (pargs->events & POLLIN) {
          flags |= B_EV_IO_READ;
        }
        if (pargs->events & POLLOUT) {
          flags |= B_EV_IO_WRITE;
        }
        dd->main_loop_id = b_input_add(pargs->fd, flags,
                                       discord_ws_service_loop, ic);
        break;
      }
    case LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED:
    case LWS_CALLBACK_GET_THREAD_ID:
    case LWS_CALLBACK_LOCK_POLL:
    case LWS_CALLBACK_UNLOCK_POLL:
    case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS:
    case LWS_CALLBACK_PROTOCOL_INIT:
    case LWS_CALLBACK_PROTOCOL_DESTROY:
    case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER:
    case LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH:
    case LWS_CALLBACK_WSI_CREATE:
    case LWS_CALLBACK_WSI_DESTROY:
      // Ignoring these, this block should be removed when defult is set to
      // stay silent.
      break;
    default:
      g_print("%s: unknown rsn=%d\n", __func__, reason);
      break;
  }
  return 0;
}