Beispiel #1
0
        /// <summary>
        /// Sets the user's directory information -- SNAC(02,09)
        /// </summary>
        /// <param name="sess">A <see cref="Session"/> object</param>
        /// <param name="allow"><c>true</c> if other users may search this information, <c>false</c> if not</param>
        /// <param name="firstname">A first name</param>
        /// <param name="middlename">A middle name</param>
        /// <param name="lastname">A last name</param>
        /// <param name="maidenname">A maiden name</param>
        /// <param name="nickname">A nickname</param>
        /// <param name="city">A city</param>
        /// <param name="state">A state</param>
        /// <param name="country">A country (two-letter code)</param>
        /// <param name="zip">A ZIP code</param>
        /// <param name="address">An address</param>
        public static void SetDirectoryInformation(
            Session sess, bool allow,
            string firstname, string middlename, string lastname, string maidenname, string nickname,
            string city, string state, string country, string zip, string address)
        {
            SNACHeader sh = new SNACHeader();

            sh.FamilyServiceID = (ushort)SNACFamily.LocationService;
            sh.FamilySubtypeID = (ushort)LocationServices.UpdateDirectoryInfoRequest;



            ByteStream stream = new ByteStream();

            using (TlvBlock tlvs = new TlvBlock())
            {
                tlvs.WriteUshort(0x001A, (ushort)((allow) ? 0x0001 : 0x0000));
                tlvs.WriteString(DIRECTORY_FIRSTNAME, firstname, Encoding.ASCII);
                tlvs.WriteString(DIRECTORY_MIDDLENAME, middlename, Encoding.ASCII);
                tlvs.WriteString(DIRECTORY_LASTNAME, lastname, Encoding.ASCII);
                tlvs.WriteString(DIRECTORY_MAIDENNAME, maidenname, Encoding.ASCII);
                tlvs.WriteString(DIRECTORY_COUNTRY, country, Encoding.ASCII);
                tlvs.WriteString(DIRECTORY_STATE, state, Encoding.ASCII);
                tlvs.WriteString(DIRECTORY_CITY, city, Encoding.ASCII);
                tlvs.WriteString(DIRECTORY_NICKNAME, nickname, Encoding.ASCII);
                tlvs.WriteString(DIRECTORY_ZIPCODE, zip, Encoding.ASCII);
                tlvs.WriteString(DIRECTORY_ADDRESS, address, Encoding.ASCII);
                stream.WriteByteArray(tlvs.GetBytes());
            }

            SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, stream));
        }
Beispiel #2
0
 byte[] ISegment.GetBytes()
 {
     using (ByteStream buffer = new ByteStream())
     {
         buffer.WriteUshort((ushort)item.Type);
         buffer.WriteByte((byte)item.Flags);
         buffer.WriteByte((byte)item.Data.Length);
         buffer.WriteByteArray(item.Data);
         return(buffer.GetBytes());
     }
 }
Beispiel #3
0
        public void TestByteStreamNumberWriting()
        {
            ByteStream stream = new ByteStream();
            stream.WriteByte(0x08);
            stream.WriteUshort(0x4164);
            stream.WriteUint(0x7269656e);
            stream.WriteByteArray(new byte[] {0x6e, 0x65});

            Assert.AreEqual(testData.Length, stream.GetByteCount());
            ByteStream testStream = new ByteStream(stream.GetBytes());
            Assert.AreEqual("Adrienne", testStream.ReadString(testStream.ReadByte(), Encoding.ASCII));
        }
Beispiel #4
0
        /// <summary>
        /// Sets the user's interests list -- SNAC(02,0F)
        /// </summary>
        /// <param name="sess">A <see cref="Session"/> object</param>
        /// <param name="allow"><c>true</c> if other users may search this information, <c>false</c> if not</param>
        /// <param name="interests">An array of interest names</param>
        /// <remarks>
        /// OSCAR allows a user to set up to five interests. If <paramref name="interests"/> contains
        /// more than five items, only the first five are used.
        /// </remarks>
        public static void SetInterestsInformation(Session sess, bool allow, string[] interests)
        {
            SNACHeader sh = new SNACHeader();

            sh.FamilyServiceID = (ushort)SNACFamily.LocationService;
            sh.FamilySubtypeID = (ushort)LocationServices.UpdateInterestsRequest;



            ByteStream stream = new ByteStream();

            using (TlvBlock tlvs = new TlvBlock())
            {
                tlvs.WriteUshort(INTERESTS_ALLOWSEARCH, (ushort)((allow) ? 0x0001 : 0x0000));
                for (int i = 0; i < interests.Length && i < 5; i++)
                {
                    tlvs.WriteString(INTERESTS_INTEREST, interests[i], Encoding.ASCII);
                }
                stream.WriteByteArray(tlvs.GetBytes());
            }

            SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, stream));
        }
Beispiel #5
0
 byte[] ISegment.GetBytes()
 {
     using (ByteStream buffer = new ByteStream())
     {
         buffer.WriteUshort((ushort)item.Type);
         buffer.WriteByte((byte)item.Flags);
         buffer.WriteByte((byte)item.Data.Length);
         buffer.WriteByteArray(item.Data);
         return buffer.GetBytes();
     }
 }
Beispiel #6
0
        /// <summary>
        /// Uploads a buddy icon to the AIM servers
        /// </summary>
        /// <param name="filename">The filename of the icon to upload</param>
        public void UploadBuddyIcon(string filename)
        {
            // Check to make sure the local file exists
            if (!File.Exists(filename))
            {
                OnBuddyIconUploadFailed(BartReplyCode.NotFound);
                return;
            }

            byte[] data = null;
            using (StreamReader reader = new StreamReader(filename))
            {
                if (reader.BaseStream.Length > 7168) // 7KB
                {
                    OnBuddyIconUploadFailed(BartReplyCode.TooBig);
                    return;
                }

                if (!VerifyIcon(filename))
                {
                    OnBuddyIconUploadFailed(BartReplyCode.DimensionsTooBig);
                    return;
                }

                data = new byte[reader.BaseStream.Length];
                int index = 0;
                while (index < data.Length)
                {
                    index += reader.BaseStream.Read(data, index, data.Length - index);
                }
            }

            SNACHeader sh = new SNACHeader();
            sh.FamilyServiceID = SNAC_BART_FAMILY;
            sh.FamilySubtypeID = BART_UPLOAD;
            sh.Flags = 0;

            ByteStream stream = new ByteStream();
            stream.WriteUshort((ushort)BartTypeId.BuddyIcon);
            stream.WriteUshort((ushort)data.Length);
            stream.WriteByteArray(data);

            SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(parent, sh, stream));
        }
Beispiel #7
0
        /// <summary>
        /// Invites an AIM user to an AOL chatroom
        /// </summary>
        /// <param name="chatroom">The <see cref="ChatRoom"/> describing the chatroom</param>
        /// <param name="screenName">The screenname of the user to invite</param>
        /// <param name="message">A message to send along with the invitation</param>
        public Cookie InviteToChatRoom(ChatRoom chatroom, string screenName, string message)
        {
            if (!parent.LoggedIn)
            {
                throw new NotLoggedInException();
            }

            SNACHeader sh = new SNACHeader();
            sh.FamilyServiceID = SNAC_ICBM_FAMILY;
            sh.FamilySubtypeID = ICBM_OUTGOING_MESSAGE;

            Cookie cookie = Cookie.CreateCookieForSending();

            Encoding enc = Encoding.ASCII;
            byte destlength = (byte) enc.GetByteCount(screenName);
            ushort messagelength = (ushort) enc.GetByteCount(message);
            byte roomnamelength = (byte) enc.GetByteCount(chatroom.FullName);

            ByteStream stream = new ByteStream();
            InsertIcbmHeader(stream, cookie, 0x0002, screenName);

            ByteStream header = new ByteStream();
            header.WriteUshort(0x0000);
            header.WriteByteArray(cookie.ToByteArray());
            header.WriteUint(0x748F2420);
            header.WriteUint(0x628711D1);
            header.WriteUint(0x82224445);
            header.WriteUint(0x53540000);

            using (TlvBlock tlv05 = new TlvBlock())
            {
                tlv05.WriteUshort(0x000A, 0x0001);
                tlv05.WriteEmpty(0x000F);
                tlv05.WriteString(0x000C, message, enc);

                ByteStream tlv2711 = new ByteStream();
                tlv2711.WriteUshort(chatroom.Exchange);
                tlv2711.WriteByte(roomnamelength);
                tlv2711.WriteString(chatroom.FullName, enc);
                tlv2711.WriteUshort(chatroom.Instance);

                tlv05.WriteByteArray(0x2711, tlv2711.GetBytes());

                header.WriteByteArray(tlv05.GetBytes());
            }

            stream.WriteUshort(0x0005);
            stream.WriteUshort((ushort) header.GetByteCount());
            stream.WriteByteArray(header.GetBytes());

            SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(parent, sh, stream));

            return cookie;
        }
Beispiel #8
0
        /// <summary>
        /// Sets the away message and/or profile of the client
        /// </summary>
        /// <param name="awayMessage">The away message to set</param>
        /// <param name="profile">The profile to set</param>
        private void SetAwayMessageProfileInternal(string awayMessage, string profile)
        {
            // Build the SNAC header
            SNACHeader sh = new SNACHeader();
            sh.FamilyServiceID = SNAC_LOCATION_FAMILY;
            sh.FamilySubtypeID = LOCATION_PARAMETER_USERINFO;

            ByteStream stream = new ByteStream();
            using (TlvBlock tlvs = new TlvBlock())
            {
                if (profile != null)
                {
                    Encoding profileEncoding = UtilityMethods.FindBestOscarEncoding(profile);
                    tlvs.WriteString(LOCATION_PROFILE_ENCODING, Marshal.EncodingToAolMime(profileEncoding), Encoding.ASCII);
                    tlvs.WriteString(LOCATION_PROFILE, profile, profileEncoding);
                }
                if (awayMessage != null)
                {
                    Encoding awayMessageEncoding = UtilityMethods.FindBestOscarEncoding(awayMessage);
                    tlvs.WriteString(LOCATION_AWAYMESSAGE_ENCODING, Marshal.EncodingToAolMime(awayMessageEncoding),
                                     Encoding.ASCII);
                    tlvs.WriteString(LOCATION_AWAYMESSAGE, awayMessage, awayMessageEncoding);
                }
                stream.WriteByteArray(tlvs.GetBytes());
            }

            SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(parent, sh, stream));
        }
Beispiel #9
0
        /// <summary>
        /// Returns an MD5 hash of the client's password, an authorization key, and a constant string
        /// </summary>
        /// <param name="authkey">The authorization key sent by the server</param>
        /// <returns>A 16-byte MD5 hash</returns>
        /// <remarks>
        /// <para>
        /// The hashing process is fairly simple:
        /// <list>
        /// <item>The authorization key is put into a buffer</item>
        /// <item>The password itself is hashed via MD5 and appended to the buffer</item>
        /// <item>The constant string, "AOL Instant Messenger (SM)", is appended to the buffer in plaintext</item>
        /// <item>The entire buffer is MD5 hashed and returned to the caller</item>
        /// </list>
        /// </para>
        /// <para>
        /// This method exists to prevent the password from having to be passed around in a data structure
        /// </para>
        /// </remarks>
        protected internal byte[] HashPassword(byte[] authkey)
        {
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();

            ByteStream stream = new ByteStream();
            stream.WriteByteArray(authkey);
            stream.WriteByteArray(md5.ComputeHash(Encoding.ASCII.GetBytes(_password)));
            stream.WriteString(Constants.AIM_MD5_STRING, Encoding.ASCII);

            return md5.ComputeHash(stream.GetBytes());
        }
Beispiel #10
0
        /// <summary>
        /// This method is invoked when the connection is complete
        /// </summary>
        protected virtual void OnConnectionFinished()
        {
            Connecting = true;

            // Read in the first ten bytes (6 byte FLAP channel 0x01 + 0x00000001)
            // of the connection handshake
            byte[] serverhandshake = new byte[10];
            try
            {
                int bytesreceived = 0;
                int receiveindex  = 0;
                lock (socket)
                {
                    while (bytesreceived < 10)
                    {
                        bytesreceived = socket.Read(serverhandshake, receiveindex, 10 - receiveindex);
                        receiveindex += bytesreceived;
                    }
                }
            }
            catch (Exception ex)
            {
                Logging.WriteString("Can't read handshake from server: {0}, connection {1}", ex.Message, ID);
                DisconnectFromServer(true);
                return;
            }
            finally
            {
                serverhandshake = null;
            }

            // Construct our reply to the connection handshake
            using (ByteStream clientHandshake = new ByteStream())
            {
                FLAPHeader fh;
                fh.Channel = 0x01;
                fh.DatagramSequenceNumber = FLAPSequence;
                fh.DataSize = (ushort)(4 + ((cookie == null) ? 0 : 4 + cookie.GetByteCount()));

                clientHandshake.PrependOscarHeaders(fh, null);
                clientHandshake.WriteUint(Constants.PROTOCOL_VERSION);
                if (cookie != null)
                {
                    clientHandshake.WriteUshort(0x0006);
                    clientHandshake.WriteUshort((ushort)cookie.GetByteCount());
                    clientHandshake.WriteByteArray(cookie.ToByteArray());
                }

                try
                {
                    lock (socket)
                    {
                        socket.Write(clientHandshake.GetBytes());
                    }
                }
                catch (Exception ex)
                {
                    Logging.WriteString("Couldn't send handshake to server: {0}, connection {1}", ex.Message, ID);
                    DisconnectFromServer(true);
                    return;
                }
            }

            StopTimeoutPeriod();
            Connecting = true;

            // And the handshaking is done. Auth connection will send
            // SNAC(17,06) and any other connection will receive SNAC(01,03)
            OnServerConnectionCompleted();
        }
Beispiel #11
0
        /// <summary>
        /// Sends a list of the client's capabilities to the server
        /// </summary>
        /// <remarks>This method sends SNAC(0x02,0x04)</remarks>
        public void ReportClientCapabilities()
        {
            if (parent.ClientCapabilities != Capabilities.None)
            {
                SNACHeader sh = new SNACHeader();
                sh.FamilyServiceID = SNAC_LOCATION_FAMILY;
                sh.FamilySubtypeID = LOCATION_PARAMETER_USERINFO;

                // Build the capabilities list, TLV type 0x0005
                byte[] caps = CapabilityProcessor.GetCapabilityArray(parent.ClientCapabilities);
                ByteStream stream = new ByteStream();
                stream.WriteUshort(LOCATION_CAPABILITIES);
                stream.WriteUshort((ushort)caps.Length);
                stream.WriteByteArray(caps);

                SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(parent, sh, stream));
            }
        }
Beispiel #12
0
        /// <summary>
        /// Sends an ICBM on channel 1 -- SNAC(04,06)
        /// </summary>
        /// <param name="destination">The screenname to receive the IM</param>
        /// <param name="message">The message to send</param>
        /// <param name="flags">A <see cref="OutgoingMessageFlags"/> enumeration specifying what
        /// additional information should be sent with the message</param>
        private Cookie SendMessageThroughServer(string destination, string message, OutgoingMessageFlags flags)
        {
            SNACHeader sh = new SNACHeader();
                    sh.FamilyServiceID = SNAC_ICBM_FAMILY;
                    sh.FamilySubtypeID = ICBM_OUTGOING_MESSAGE;

                    byte[] default_features = new byte[] { 0x01, 0x01, 0x01, 0x02 };
                    Cookie cookie = Cookie.CreateCookieForSending();
                    Encoding encoding = UtilityMethods.FindBestOscarEncoding(message);

                    ByteStream stream = new ByteStream();

                    InsertIcbmHeader(stream, cookie, 0x0001, destination);
                    using (TlvBlock tlvs = new TlvBlock())
                    {
                        // Write in TLV 0x0002: a text message
                        using (TlvBlock tlv02 = new TlvBlock())
                        {
                            tlv02.WriteByteArray(0x0501, default_features);
                            ByteStream feature0101 = new ByteStream();
                            feature0101.WriteUshort(Marshal.EncodingToCharset(encoding));
                            feature0101.WriteUshort(0x0000);
                            feature0101.WriteString(message, encoding);
                            tlv02.WriteByteArray(0x0101, feature0101.GetBytes());
                            tlvs.WriteByteArray(0x0002, tlv02.GetBytes());
                        }

                        // Pack in optional TLVs
                        if ((flags & OutgoingMessageFlags.AutoResponse) != 0)
                        {
                            tlvs.WriteEmpty(0x0004);
                        }
                        else
                        {
                            // Request a notification of delivery - note that this can't happen
                            // with an AutoResponse flag set, otherwise the message is bounced
                            tlvs.WriteEmpty(0x0003);
                        }

                        if ((flags & OutgoingMessageFlags.DeliverOffline) != 0
                            && (flags & OutgoingMessageFlags.AutoResponse) == 0)
                        {
                            // Try to store if the user is offline
                            tlvs.WriteEmpty(0x0006);
                        }

                        // Add the TLVs to the byte stream
                        stream.WriteByteArray(tlvs.GetBytes());
                    }

                    // Cache the message for delivery updates
                    messageStatuses.Add(sh.RequestID, new MessageStatusEventArgs(cookie, destination));

                    // Send that sucker off
                    SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(parent, sh, stream));
                    return cookie;
        }
Beispiel #13
0
        /// <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));
        }
Beispiel #14
0
 /// <summary>
 /// Inserts an ICBM header
 /// </summary>
 private static void InsertIcbmHeader(ByteStream stream, Cookie cookie, ushort channel, string screenName)
 {
     stream.WriteByteArray(cookie.ToByteArray());
             stream.WriteUshort(channel);
             stream.WriteByte((byte)Encoding.ASCII.GetByteCount(screenName));
             stream.WriteString(screenName, Encoding.ASCII);
 }
Beispiel #15
0
        /// <summary>
        /// Sends a typing notification
        /// </summary>
        /// <param name="screenName">The screenname to receive the typing notification</param>
        /// <param name="tn">A <see cref="TypingNotification"/> enumeration specifying what
        /// notification to send</param>
        /// <exception cref="NotLoggedInException">Thrown when the <see cref="Session"/> is not logged in</exception>
        public void SendTypingNotification(string screenName, TypingNotification tn)
        {
            if (!parent.LoggedIn)
            {
                throw new NotLoggedInException();
            }

            DirectIMConnection conn = parent.Connections.GetDirectIMByScreenname(screenName);
            if (conn != null)
            {
                if (conn.Connected)
                {
                    // TODO:  send DIM typing notifications
                }
            }

            // Construct SNAC(04,14)
            SNACHeader sh = new SNACHeader();
            sh.FamilyServiceID = SNAC_ICBM_FAMILY;
            sh.FamilySubtypeID = ICBM_TYPING_NOTIFICATION;

            ByteStream stream = new ByteStream();
            stream.WriteByteArray(new byte[] {0, 0, 0, 0, 0, 0, 0, 0});
            stream.WriteUshort(0x0001);
            stream.WriteByte((byte) Encoding.ASCII.GetByteCount(screenName));
            stream.WriteString(screenName, Encoding.ASCII);
            stream.WriteUshort((ushort) tn);

            SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(parent, sh, stream));
        }
Beispiel #16
0
        /// <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));
        }
Beispiel #17
0
        /// <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));
        }
Beispiel #18
0
        /// <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));
        }