Example #1
0
static void
msn_dc_send_cb(gpointer data, gint fd, PurpleInputCondition cond)
{
	MsnDirectConn *dc = data;
	MsnDirectConnPacket *p;
	int bytes_to_send;
	int bytes_sent;

	g_return_if_fail(dc != NULL);
	g_return_if_fail(fd != -1);

	if (g_queue_is_empty(dc->out_queue)) {
		if (dc->send_handle != 0) {
			purple_input_remove(dc->send_handle);
			dc->send_handle = 0;
		}
		return;
	}

	p = g_queue_peek_head(dc->out_queue);

	if (dc->msg_pos < 0) {
		/* First we send the length of the packet */
		guint32 len = GUINT32_TO_LE(p->length);
		bytes_sent = send(fd, &len, 4, 0);
		if (bytes_sent < 0) {
			if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
				return;

			purple_debug_warning("msn", "msn_dc_send_cb: send error\n");
			msn_dc_destroy(dc);
			return;
		}
		dc->msg_pos = 0;
	}

	bytes_to_send = p->length - dc->msg_pos;
	bytes_sent = send(fd, p->data + dc->msg_pos, bytes_to_send, 0);
	if (bytes_sent < 0) {
		if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
			return;

		purple_debug_warning("msn", "msn_dc_send_cb: send error\n");
		msn_dc_destroy(dc);
		return;
	}

	dc->progress = TRUE;

	dc->msg_pos += bytes_sent;
	if (dc->msg_pos == p->length) {
		if (p->sent_cb != NULL)
			p->sent_cb(p);

		g_queue_pop_head(dc->out_queue);
		msn_dc_destroy_packet(p);

		dc->msg_pos = -1;
	}
}
Example #2
0
void
msn_slplink_remove_slpcall(MsnSlpLink *slplink, MsnSlpCall *slpcall)
{
	/*
	if (slplink->dc != NULL && slplink->dc->state == DC_STATE_ESTABLISHED)
		msn_dc_unref(slplink->dc);
	*/

	slplink->slp_calls = g_list_remove(slplink->slp_calls, slpcall);

	/* The slplink has no slpcalls in it, release it from MSN_SB_FLAG_FT.
	 * If nothing else is using it then this might cause swboard to be
	 * destroyed. */
	if (slplink->slp_calls == NULL && slplink->swboard != NULL) {
		slplink->swboard->slplinks = g_list_remove(slplink->swboard->slplinks, slplink);
		msn_switchboard_release(slplink->swboard, MSN_SB_FLAG_FT);
		slplink->swboard = NULL;
	}

	/* The slplink has no slpcalls in it, release it from the DC. */
	if (slplink->slp_calls == NULL && slplink->dc != NULL) {
		slplink->dc->slplink = NULL;
		msn_dc_destroy(slplink->dc);
		slplink->dc = NULL;
	}
}
Example #3
0
void
msn_dc_fallback_to_sb(MsnDirectConn *dc)
{
	MsnSlpLink *slplink;
	MsnSlpCall *slpcall;
	GQueue *queue = NULL;

	purple_debug_info("msn", "msn_dc_fallback_to_sb %p\n", dc);

	g_return_if_fail(dc != NULL);

	slpcall = dc->slpcall;
	slplink = msn_slplink_ref(dc->slplink);
	if (slpcall && !g_queue_is_empty(dc->out_queue)) {
		queue = dc->out_queue;
		dc->out_queue = NULL;
	}

	msn_dc_destroy(dc);

	if (slpcall) {
		msn_slpcall_session_init(slpcall);
		if (queue) {
			while (!g_queue_is_empty(queue)) {
				MsnDirectConnPacket *p = g_queue_pop_head(queue);
				msn_slplink_send_msgpart(slplink, (MsnSlpMessage*)p->part->ack_data);
				msn_dc_destroy_packet(p);
			}
			g_queue_free(queue);
		}
	}
	msn_slplink_unref(slplink);
}
Example #4
0
void
msn_slplink_remove_slpcall(MsnSlpLink *slplink, MsnSlpCall *slpcall)
{
	/*
	if (slplink->dc != NULL && slplink->dc->state == DC_STATE_ESTABLISHED)
		msn_dc_unref(slplink->dc);
	*/

	slplink->slp_calls = g_list_remove(slplink->slp_calls, slpcall);

	/* The slplink has no slpcalls in it, release it from MSN_SB_FLAG_FT.
	 * If nothing else is using it then this might cause swboard to be
	 * destroyed. */
	if (slplink->slp_calls == NULL && slplink->swboard != NULL) {
		slplink->swboard->slplinks = g_list_remove(slplink->swboard->slplinks, slplink);
		msn_switchboard_release(slplink->swboard, MSN_SB_FLAG_FT);
		slplink->swboard = NULL;
	}

	if (slplink->dc != NULL) {
		if ((slplink->dc->state != DC_STATE_ESTABLISHED && slplink->dc->slpcall == slpcall)
		 || (slplink->slp_calls == NULL)) {
			/* The DC is not established and its corresponding slpcall is dead,
			 * or the slplink has no slpcalls in it and no longer needs the DC.
			 */
			slplink->dc->slplink = NULL;
			msn_dc_destroy(slplink->dc);
			slplink->dc = NULL;
		}
	}
}
Example #5
0
static void
msn_slplink_destroy(MsnSlpLink *slplink)
{
	MsnSession *session;

	if (purple_debug_is_verbose())
		purple_debug_info("msn", "slplink_destroy: slplink(%p)\n", slplink);

	if (slplink->swboard != NULL) {
		slplink->swboard->slplinks = g_list_remove(slplink->swboard->slplinks, slplink);
		slplink->swboard = NULL;
	}

	session = slplink->session;

	if (slplink->dc != NULL) {
		slplink->dc->slplink = NULL;
		msn_dc_destroy(slplink->dc);
		slplink->dc = NULL;
	}

	while (slplink->slp_calls != NULL)
		msn_slpcall_destroy(slplink->slp_calls->data);

	g_queue_free(slplink->slp_msg_queue);

	session->slplinks =
		g_list_remove(session->slplinks, slplink);

	g_free(slplink->remote_user);

	g_free(slplink);
}
Example #6
0
static gboolean
msn_dc_timeout(gpointer data)
{
	MsnDirectConn *dc = data;

	g_return_val_if_fail(dc != NULL, FALSE);

	if (dc->progress) {
		dc->progress = FALSE;
		return TRUE;
	} else {
		dc->timeout_handle = 0;
		msn_dc_destroy(dc);
		return FALSE;
	}
}
Example #7
0
static void
msn_dc_recv_cb(gpointer data, gint fd, PurpleInputCondition cond)
{
	MsnDirectConn *dc;
	int free_buf_space;
	int bytes_received;
	guint32 packet_length;

	g_return_if_fail(data != NULL);
	g_return_if_fail(fd != -1);

	dc = data;
	free_buf_space = dc->in_size - dc->in_pos;

	bytes_received = recv(fd, dc->in_buffer + dc->in_pos, free_buf_space, 0);
	if (bytes_received < 0) {
		if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
			return;

		purple_debug_warning("msn", "msn_dc_recv_cb: recv error\n");

		if(dc->state != DC_STATE_ESTABLISHED)
			msn_dc_fallback_to_sb(dc);
		else
			msn_dc_destroy(dc);
		return;

	} else if (bytes_received == 0) {
		/* EOF. Remote side closed connection. */
		purple_debug_info("msn", "msn_dc_recv_cb: recv EOF\n");

		if(dc->state != DC_STATE_ESTABLISHED)
			msn_dc_fallback_to_sb(dc);
		else
			msn_dc_destroy(dc);
		return;
	}

	dc->progress = TRUE;

	dc->in_pos += bytes_received;

	/* Wait for packet length */
	while (dc->in_pos >= 4) {
		packet_length = GUINT32_FROM_LE(*((guint32*)dc->in_buffer));

		if (packet_length > DC_MAX_PACKET_SIZE) {
			/* Oversized packet */
			purple_debug_warning("msn", "msn_dc_recv_cb: oversized packet received\n");
			return;
		}

		/* Wait for the whole packet to arrive */
		if (dc->in_pos < 4 + packet_length)
			return;

		switch (msn_dc_process_packet(dc, packet_length)) {
		case DC_PROCESS_CLOSE:
			return;

		case DC_PROCESS_FALLBACK:
			purple_debug_warning("msn", "msn_dc_recv_cb: packet processing error, fall back to SB\n");
			msn_dc_fallback_to_sb(dc);
			return;

		}

		if (dc->in_pos > packet_length + 4) {
			g_memmove(dc->in_buffer, dc->in_buffer + 4 + packet_length, dc->in_pos - packet_length - 4);
		}

		dc->in_pos -= packet_length + 4;
	}
}