Example #1
0
static void
process_complete_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg, MsnP2PInfo *info)
{
	MsnSlpCall *slpcall;

	slpcall = msn_slp_process_msg(slplink, slpmsg);

	if (slpcall == NULL) {
		msn_slpmsg_destroy(slpmsg);
		return;
	}

	purple_debug_info("msn", "msn_slplink_process_msg: slpmsg complete\n");

	if (msn_p2p_info_require_ack(slpmsg->p2p_info))
	{
		/* Release all the messages and send the ACK */

		if (slpcall->wait_for_socket) {
			/*
			 * Save ack for later because we have to send
			 * a 200 OK message to the previous direct connect
			 * invitation before ACK but the listening socket isn't
			 * created yet.
			 */
			purple_debug_info("msn", "msn_slplink_process_msg: save ACK\n");

			slpcall->slplink->dc->prev_ack = msn_slpmsg_ack_new(slplink, info);
		} else if (!slpcall->wasted) {
			purple_debug_info("msn", "msn_slplink_process_msg: send ACK\n");

			msn_slplink_send_ack(slplink, info);
			msn_slplink_send_queued_slpmsgs(slplink);
		}
	}

	msn_slpmsg_destroy(slpmsg);

	if (!slpcall->wait_for_socket && slpcall->wasted)
		msn_slpcall_destroy(slpcall);
}
Example #2
0
void
msn_slplink_process_msg(MsnSlpLink *slplink, MsnSlpHeader *header, const char *data, gsize len)
{
	MsnSlpMessage *slpmsg;
	guint64 offset;
	PurpleXfer *xfer = NULL;

	if (header->total_size < header->length)
	{
		purple_debug_error("msn", "This can't be good\n");
		g_return_if_reached();
	}

	offset = header->offset;

	if (offset == 0)
	{
		slpmsg = msn_slpmsg_new(slplink);
		slpmsg->id = header->id;
		slpmsg->session_id = header->session_id;
		slpmsg->size = header->total_size;
		slpmsg->flags = header->flags;

		if (slpmsg->session_id)
		{
			if (slpmsg->slpcall == NULL)
				slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, slpmsg->session_id);

			if (slpmsg->slpcall != NULL)
			{
				if (slpmsg->flags == 0x20 ||
				    slpmsg->flags == 0x1000020 || slpmsg->flags == 0x1000030)
				{
					xfer = slpmsg->slpcall->xfer;
					if (xfer != NULL)
					{
						slpmsg->ft = TRUE;
						slpmsg->slpcall->xfer_msg = slpmsg;

						purple_xfer_ref(xfer);
						purple_xfer_start(xfer,	-1, NULL, 0);

						if (xfer->data == NULL) {
							purple_xfer_unref(xfer);
							msn_slpmsg_destroy(slpmsg);
							g_return_if_reached();
						} else {
							purple_xfer_unref(xfer);
						}
					}
				}
			}
		}
		if (!slpmsg->ft && slpmsg->size)
		{
			slpmsg->buffer = g_try_malloc(slpmsg->size);
			if (slpmsg->buffer == NULL)
			{
				purple_debug_error("msn", "Failed to allocate buffer for slpmsg\n");
				msn_slpmsg_destroy(slpmsg);
				return;
			}
		}
	}
	else
	{
		slpmsg = msn_slplink_message_find(slplink, header->session_id, header->id);
		if (slpmsg == NULL)
		{
			/* Probably the transfer was canceled */
			purple_debug_error("msn", "Couldn't find slpmsg\n");
			return;
		}
	}

	if (slpmsg->ft)
	{
		xfer = slpmsg->slpcall->xfer;
		slpmsg->slpcall->u.incoming_data =
				g_byte_array_append(slpmsg->slpcall->u.incoming_data, (const guchar *)data, len);
		purple_xfer_prpl_ready(xfer);
	}
	else if (slpmsg->size && slpmsg->buffer)
	{
		if (G_MAXSIZE - len < offset || (offset + len) > slpmsg->size || slpmsg->offset != offset)
		{
			purple_debug_error("msn",
				"Oversized slpmsg - msgsize=%lld offset=%" G_GUINT64_FORMAT " len=%" G_GSIZE_FORMAT "\n",
				slpmsg->size, offset, len);
			g_return_if_reached();
		} else {
			memcpy(slpmsg->buffer + offset, data, len);
			slpmsg->offset += len;
		}
	}

	if ((slpmsg->flags == 0x20 ||
	     slpmsg->flags == 0x1000020 || slpmsg->flags == 0x1000030) &&
		(slpmsg->slpcall != NULL))
	{
		slpmsg->slpcall->progress = TRUE;

		if (slpmsg->slpcall->progress_cb != NULL)
		{
			slpmsg->slpcall->progress_cb(slpmsg->slpcall, slpmsg->size,
										 len, offset);
		}
	}

#if 0
	if (slpmsg->buffer == NULL)
		return;
#endif

	if (header->offset + header->length >= header->total_size)
	{
		/* All the pieces of the slpmsg have been received */
		MsnSlpCall *slpcall;

		slpcall = msn_slp_process_msg(slplink, slpmsg);

		if (slpcall == NULL) {
			msn_slpmsg_destroy(slpmsg);
			return;
		}

		purple_debug_info("msn", "msn_slplink_process_msg: slpmsg complete\n");

		if (/* !slpcall->wasted && */ slpmsg->flags == 0x100)
		{
#if 0
			MsnDirectConn *directconn;

			directconn = slplink->directconn;
			if (!directconn->acked)
				msn_directconn_send_handshake(directconn);
#endif
		}
		else if (slpmsg->flags == 0x00 || slpmsg->flags == 0x1000000 ||
		         slpmsg->flags == 0x20 || slpmsg->flags == 0x1000020 ||
		         slpmsg->flags == 0x1000030)
		{
			/* Release all the messages and send the ACK */

			if (slpcall->wait_for_socket) {
				/*
				 * Save ack for later because we have to send
				 * a 200 OK message to the previous direct connect
				 * invitation before ACK but the listening socket isn't
				 * created yet.
				 */
				purple_debug_info("msn", "msn_slplink_process_msg: save ACK\n");

				slpcall->slplink->dc->prev_ack = msn_slplink_create_ack(slplink, header);
			} else if (!slpcall->wasted) {
				purple_debug_info("msn", "msn_slplink_process_msg: send ACK\n");

				msn_slplink_send_ack(slplink, header);
				msn_slplink_send_queued_slpmsgs(slplink);
			}
		}

		msn_slpmsg_destroy(slpmsg);

		if (!slpcall->wait_for_socket && slpcall->wasted)
			msn_slpcall_destroy(slpcall);
	}
}
Example #3
0
void
msn_slplink_process_msg(MsnSlpLink *slplink, MsnMessage *msg)
{
	MsnSlpMessage *slpmsg;
	const char *data;
	gsize offset;
	gsize len;

#ifdef MSN_DEBUG_SLP
	msn_slpmsg_show(msg);
#endif

#ifdef MSN_DEBUG_SLP_FILES
	debug_msg_to_file(msg, FALSE);
#endif

	if (msg->msnslp_header.total_size < msg->msnslp_header.length)
	{
		purple_debug_error("msn", "This can't be good\n");
		g_return_if_reached();
	}

	slpmsg = NULL;
	data = msn_message_get_bin_data(msg, &len);

	/*
		OVERHEAD!
		if (msg->msnslp_header.length < msg->msnslp_header.total_size)
	 */

	offset = msg->msnslp_header.offset;

	if (offset == 0)
	{
		slpmsg = msn_slpmsg_new(slplink);
		slpmsg->id = msg->msnslp_header.id;
		slpmsg->session_id = msg->msnslp_header.session_id;
		slpmsg->size = msg->msnslp_header.total_size;
		slpmsg->flags = msg->msnslp_header.flags;

		if (slpmsg->session_id)
		{
			if (slpmsg->slpcall == NULL)
				slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, slpmsg->session_id);

			if (slpmsg->slpcall != NULL)
			{
				if (slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030)
				{
					PurpleXfer *xfer;

					xfer = slpmsg->slpcall->xfer;

					if (xfer != NULL)
					{
						purple_xfer_ref(xfer);
						purple_xfer_start(xfer,	0, NULL, 0);

						if (xfer->data == NULL) {
							purple_xfer_unref(xfer);
							return;
						} else {
							purple_xfer_unref(xfer);
							slpmsg->fp = xfer->dest_fp;
							xfer->dest_fp = NULL; /* Disable double fclose() */
						}
					}
				}
			}
		}
		if (!slpmsg->fp && slpmsg->size)
		{
			slpmsg->buffer = g_try_malloc(slpmsg->size);
			if (slpmsg->buffer == NULL)
			{
				purple_debug_error("msn", "Failed to allocate buffer for slpmsg\n");
				return;
			}
		}
	}
	else
	{
		slpmsg = msn_slplink_message_find(slplink, msg->msnslp_header.session_id, msg->msnslp_header.id);
	}

	if (slpmsg == NULL)
	{
		/* Probably the transfer was canceled */
		purple_debug_error("msn", "Couldn't find slpmsg\n");
		return;
	}

	if (slpmsg->fp)
	{
		/* fseek(slpmsg->fp, offset, SEEK_SET); */
		len = fwrite(data, 1, len, slpmsg->fp);
	}
	else if (slpmsg->size)
	{
		if (G_MAXSIZE - len < offset || (offset + len) > slpmsg->size)
		{
			purple_debug_error("msn", "Oversized slpmsg\n");
			g_return_if_reached();
		}
		else
			memcpy(slpmsg->buffer + offset, data, len);
	}

	if ((slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030) &&
		(slpmsg->slpcall != NULL))
	{
		slpmsg->slpcall->progress = TRUE;

		if (slpmsg->slpcall->progress_cb != NULL)
		{
			slpmsg->slpcall->progress_cb(slpmsg->slpcall, slpmsg->size,
										 len, offset);
		}
	}

#if 0
	if (slpmsg->buffer == NULL)
		return;
#endif

	if (msg->msnslp_header.offset + msg->msnslp_header.length
		>= msg->msnslp_header.total_size)
	{
		/* All the pieces of the slpmsg have been received */
		MsnSlpCall *slpcall;

		slpcall = msn_slp_process_msg(slplink, slpmsg);

		if (slpmsg->flags == 0x100)
		{
			MsnDirectConn *directconn;

			directconn = slplink->directconn;

			if (!directconn->acked)
				msn_directconn_send_handshake(directconn);
		}
		else if (slpmsg->flags == 0x0 || slpmsg->flags == 0x20 ||
				 slpmsg->flags == 0x1000030)
		{
			/* Release all the messages and send the ACK */

			msn_slplink_send_ack(slplink, msg);
			msn_slplink_unleash(slplink);
		}

		msn_slpmsg_destroy(slpmsg);

		if (slpcall != NULL && slpcall->wasted)
			msn_slp_call_destroy(slpcall);
	}
}