/// <summary> /// Gets a <see cref="DirectConnection"/> by its Rendezvous cookie /// </summary> /// <returns>The <see cref="DirectConnection"/> that corresponds to the cookie, or null if no corresponding DC is found</returns> public DirectConnection GetDirectConnectionByCookie(Cookie key, bool removefromcache) { DirectConnection retval = null; foreach (DirectConnection dc in _directconnections) { if (dc.Cookie.ToString() == key.ToString()) { retval = dc; break; } } if (retval != null && removefromcache) { _directconnections.Remove(retval); } return(retval); }
/// <summary> /// Raises the <see cref="DirectIMSessionCancelled"/> event /// </summary> /// <param name="cookie">The rendezvous cookie belonging to the cancelled session</param> /// <param name="reason">The reason for the cancellation</param> protected internal void OnDirectIMSessionCancelled(DirectConnection conn, string reason) { Connections.RemoveDirectConnection(conn.Cookie); Messages.SendDirectConnectionCancellation(conn, reason); if (this.DirectIMSessionCancelled != null) { this.DirectIMSessionCancelled(this, conn.Other, conn.Cookie, reason); } }
/// <summary> /// Cancel a direct connection attempt /// </summary> public void SendDirectConnectionCancellation(DirectConnection conn, string reason) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = SNAC_ICBM_FAMILY; sh.FamilySubtypeID = ICBM_OUTGOING_MESSAGE; ByteStream stream = new ByteStream(); InsertIcbmHeader(stream, conn.Cookie, 0x0002, conn.Other.ScreenName); using (ByteStream tlv05 = new ByteStream()) { tlv05.WriteUshort(RendezvousData.UshortFromType(RendezvousType.Cancel)); tlv05.WriteByteArray(conn.Cookie.ToByteArray()); tlv05.WriteByteArray(CapabilityProcessor.GetCapabilityArray(conn.Capability)); using (TlvBlock tlvs = new TlvBlock()) { tlvs.WriteUshort(0x000B, 0x0001); tlvs.WriteString(0x000C, reason, Encoding.ASCII); tlvs.WriteEmpty(0x0003); //KSD-SYSTEMS - commented at 02.12.2009 -> Canceling = Send Message only with Cookie //tlv05.WriteByteArray(tlvs.GetBytes()); } stream.WriteUshort(0x0005); stream.WriteUshort((ushort)tlv05.GetByteCount()); stream.WriteByteArray(tlv05.GetBytes()); } SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(parent, sh, stream)); }
/// <summary> /// Accept a direct connection attempt /// </summary> public void SendDirectConnectionAccept(DirectConnection conn) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = SNAC_ICBM_FAMILY; sh.FamilySubtypeID = ICBM_OUTGOING_MESSAGE; ByteStream stream = new ByteStream(); InsertIcbmHeader(stream, conn.Cookie, 0x0002, conn.Other.ScreenName); using (ByteStream tlv05 = new ByteStream()) { tlv05.WriteUshort(RendezvousData.UshortFromType(RendezvousType.Accept)); tlv05.WriteByteArray(conn.Cookie.ToByteArray()); tlv05.WriteByteArray(CapabilityProcessor.GetCapabilityArray(conn.Capability)); tlv05.WriteUint(0x00030000); stream.WriteUshort(0x0005); stream.WriteUshort((ushort)tlv05.GetByteCount()); stream.WriteByteArray(tlv05.GetBytes()); } SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(parent, sh, stream)); }
/// <summary> /// Sends a direct connection request /// </summary> /// <param name="conn">A <see cref="DirectConnection"/> object that will handle the request</param> public void RequestDirectConnectionInvite(DirectConnection conn) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = SNAC_ICBM_FAMILY; sh.FamilySubtypeID = ICBM_OUTGOING_MESSAGE; ByteStream stream = new ByteStream(); InsertIcbmHeader(stream, conn.Cookie, 0x0002, conn.Other.ScreenName); using (ByteStream tlv05 = new ByteStream()) { tlv05.WriteUshort(RendezvousData.UshortFromType(RendezvousType.Invite)); tlv05.WriteByteArray(conn.Cookie.ToByteArray()); tlv05.WriteByteArray(CapabilityProcessor.GetCapabilityArray(conn.Capability)); using (TlvBlock tlvs = new TlvBlock()) { tlvs.WriteUshort(DC_SEQUENCE_NUMBER, RendezvousData.UshortFromSequence(conn.Sequence)); if (conn.Sequence == RendezvousSequence.DirectOrStage1) { tlvs.WriteEmpty(0x000F); } if (!String.IsNullOrEmpty(conn.Message)) { tlvs.WriteString(DC_MESSAGE, conn.Message, Encoding.ASCII); } uint ipaddress = 0; if (conn.Method == DirectConnectionMethod.Proxied) { ipaddress = ConvertIPAddress(conn.AOLProxyIP); } else { ipaddress = ConvertIPAddress(conn.ClientIP); } tlvs.WriteUint(DC_PROXY_IP_ADDRESS, ipaddress); tlvs.WriteUint(DC_PROXY_IP_ADDRESS_COMPLIMENT, ~ipaddress); if (conn.Sequence == RendezvousSequence.DirectOrStage1) { tlvs.WriteUint(DC_CLIENT_IP_ADDRESS, ConvertIPAddress(conn.ClientIP)); } if (conn.Sequence != RendezvousSequence.Stage3) { tlvs.WriteUshort(DC_PORT, (ushort)conn.Port); tlvs.WriteUshort(DC_PORT_COMPLIMENT, (ushort)(~conn.Port)); } if (conn.Method == DirectConnectionMethod.Proxied) { tlvs.WriteEmpty(DC_USE_PROXY_FLAG); } if (conn is FileTransferConnection && conn.Sequence == RendezvousSequence.DirectOrStage1) { FileTransferConnection ftc = conn as FileTransferConnection; using (ByteStream tlv2711 = new ByteStream()) { tlv2711.WriteUshort((ushort)((ftc.TotalFiles > 1) ? 0x0002 : 0x0001)); tlv2711.WriteUshort((ushort)ftc.TotalFiles); tlv2711.WriteUint(ftc.TotalFileSize); tlv2711.WriteString(ftc.FileHeader.Name, Encoding.ASCII); tlv2711.WriteByte(0x00); tlvs.WriteByteArray(0x2711, tlv2711.GetBytes()); } tlvs.WriteString(0x2712, ftc.LocalFileNameEncoding.WebName, Encoding.ASCII); } tlv05.WriteByteArray(tlvs.GetBytes()); } stream.WriteUshort(0x0005); stream.WriteUshort((ushort)tlv05.GetByteCount()); stream.WriteByteArray(tlv05.GetBytes()); } // Acknowledgement request stream.WriteUint(0x00030000); SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(parent, sh, stream)); }
/// <summary> /// Sends a direct connection accept /// </summary> /// <param name="conn">A <see cref="DirectConnection"/> object that will handle the request</param> public void RequestDirectConnectionAccept(DirectConnection conn) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = 4; sh.FamilySubtypeID = 6; ByteStream stream = new ByteStream(); MessageManager.InsertIcbmHeader(stream, conn.Cookie, 0x0002, conn.Other.ScreenName); stream.WriteUshort(0x0005); // Type stream.WriteUshort(0x001a); // Len stream.WriteUshort(RendezvousData.UshortFromType(RendezvousType.Accept)); // Command stream.WriteByteArray(conn.Cookie.ToByteArray()); stream.WriteByteArray(CapabilityProcessor.GetCapabilityArray(conn.Capability)); SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(parent, sh, stream)); }
/// <summary> /// Performs TLV 0x2711 processing for direct connect (sendfiles, DirectIM) negotiation /// </summary> private void ProcessDirectConnectionRequest(DirectConnection conn, ByteStream stream) { if (conn.Type == RendezvousType.Accept) { // They're accepting, which means we're going to get a connection on the // listener socket set up in FileTransferManager. Do nothing here } else if (conn.Type == RendezvousType.Cancel) { DirectConnection cancelled = parent.Connections.GetDirectConnectionByCookie(conn.Cookie); if (cancelled != null) { if (cancelled is FileTransferConnection) { (cancelled as FileTransferConnection).CancelFileTransfer( "Remote user cancelled direct connection"); } else if (cancelled is DirectIMConnection) { parent.OnDirectIMSessionCancelled(cancelled, "Remote user cancelled direct connection"); } } return; } else if (conn.Type == RendezvousType.Invite) { // AIM sends a type 0x0000 when accepting...huh. if (conn.Sequence == RendezvousSequence.DirectOrStage1) { if (stream.HasMoreData && conn is FileTransferConnection) { FileTransferConnection ftconn = conn as FileTransferConnection; ftconn.SubType = stream.ReadUshort(); ftconn.TotalFiles = stream.ReadUshort(); ftconn.TotalFileSize = stream.ReadUint(); int strlen = 0; byte[] servicedata = stream.ReadByteArrayToEnd(); // The filename in an RD invite is null-terminated ASCII while (servicedata[strlen++] != 0x00) ; ftconn.FileHeader.Name = Encoding.ASCII.GetString(servicedata, 0, strlen - 1); } parent.OnDirectConnectionRequestReceived(conn.Cookie); } else if (conn.Sequence == RendezvousSequence.Stage2) { // The receipient of a previous invite wants a stage 2 proxy redirection // Shut down the server socket, we won't be getting a connection on it conn.StopListeningSocket(); SendDirectConnectionAccept(conn); conn.StartSendThroughStage2AolProxy(); } else if (conn.Sequence == RendezvousSequence.Stage3) { // Direct connection and proxy 2 failed, the sender's trying to proxy it now conn.Method = DirectConnectionMethod.Proxied; conn.ConnectToServer(); } } }