/// <summary> /// Sends a keepalive packet (FLAP channel 5) /// </summary> /// <param name="threadstate">Always <c>null</c></param> private void SendKeepalive(object threadstate) { using (ByteStream stream = new ByteStream()) { FLAPHeader fh; fh.Channel = 0x05; fh.DatagramSequenceNumber = 0; fh.DataSize = 0; stream.PrependOscarHeaders(fh, null); try { byte[] keepalive = stream.GetBytes(); Marshal.InsertUshort(keepalive, (ushort)FLAPSequence, 2); lock (socket) { socket.Write(keepalive); } Logging.WriteString("Sent keepalive over connection {0}", ID); } catch (Exception ex) { if (!isDisconnecting) { Logging.WriteString("Couldn't send keepalive: {0}, connection {1}", ex.Message, ID); DisconnectFromServer(true); } } keepAliveTimer.Change(60000, Timeout.Infinite); } }
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()); } }
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)); }
public void TestByteStreamStringWriting() { ByteStream stream = new ByteStream(); stream.WriteByte((byte) Encoding.ASCII.GetByteCount("Adrienne")); stream.WriteString("Adrienne", Encoding.ASCII); Assert.AreEqual(testData.Length, stream.GetByteCount()); byte[] data = stream.GetBytes(); for (int i = 0; i < testData.Length; i++) { Assert.AreEqual(testData[i], data[i]); } }
public byte[] GetBytes() { ByteStream buffer = new ByteStream(); buffer.WriteUshort((ushort)Encoding.UTF8.GetByteCount(item.Name)); buffer.WriteString(item.Name, Encoding.UTF8); buffer.WriteUshort(item.GroupID); buffer.WriteUshort(item.ItemID); buffer.WriteUshort(item.ItemType); if (item.Tlvs == null) { buffer.WriteUshort(0x000); } else { buffer.WriteUshort((ushort)item.Tlvs.GetByteCount()); buffer.WriteTlvBlock(item.Tlvs); } return(buffer.GetBytes()); }
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(); } }
public byte[] GetBytes() { ByteStream buffer = new ByteStream(); buffer.WriteUshort((ushort)Encoding.UTF8.GetByteCount(item.Name)); buffer.WriteString(item.Name, Encoding.UTF8); buffer.WriteUshort(item.GroupID); buffer.WriteUshort(item.ItemID); buffer.WriteUshort(item.ItemType); if (item.Tlvs == null) buffer.WriteUshort(0x000); else { buffer.WriteUshort((ushort)item.Tlvs.GetByteCount()); buffer.WriteTlvBlock(item.Tlvs); } return buffer.GetBytes(); }
/// <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()); }
/// <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(); }
/// <summary> /// Sends a status report to the OSCAR server -- SNAC(0B,03) /// </summary> /// <param name="sess">A <see cref="ISession"/> object</param> /// <remarks>libfaim does not send this report</remarks> public static void SendStatusReport(ISession sess) { SNACHeader sh = new SNACHeader(); sh.FamilyServiceID = (ushort)SNACFamily.UsageStatsService; sh.FamilySubtypeID = (ushort)UsageStatsService.UsageReport; sh.Flags = 0; sh.RequestID = Session.GetNextRequestID(); // Get the necessary strings together string sn = sess.ScreenName; // Here we start lying until I can figure out how to get *all* the values in .NET string osversion = Environment.OSVersion.ToString(); string osname = "Windows 98"; //osversion.Substring(0, osversion.LastIndexOf(" ") - 1); string osver = "4.10.67766446"; //osversion.Substring(osversion.LastIndexOf(" ") + 1); string procname = "Intel Pentium"; string winsockname = "Microsoft Corporation BSD Socket API for Windows"; string winsockver = "4.1.1998"; Encoding enc = Encoding.ASCII; byte snlength = (byte)enc.GetByteCount(sn); ushort osversionlength = (ushort)enc.GetByteCount(osversion); ushort osnamelength = (ushort)enc.GetByteCount(osname); ushort osverlength = (ushort)enc.GetByteCount(osver); ushort procnamelength = (ushort)enc.GetByteCount(procname); ushort winsocknamelength = (ushort)enc.GetByteCount(winsockname); ushort winsockverlength = (ushort)enc.GetByteCount(winsockver); ByteStream mainStream = new ByteStream(); using (ByteStream stream = new ByteStream()) { TimeSpan t = (DateTime.Now - new DateTime(1970, 1, 1)); stream.WriteUint((uint)t.Seconds); t = (DateTime.UtcNow - new DateTime(1970, 1, 1).ToUniversalTime()); stream.WriteUint((uint)t.Seconds); stream.WriteUint(0x00000000); stream.WriteUint(0x00000000); stream.WriteUint(0x00000000); stream.WriteUint(0x00000000); stream.WriteByte(snlength); stream.WriteString(sn, Encoding.ASCII); stream.WriteUshort(osnamelength); stream.WriteString(osname, Encoding.ASCII); stream.WriteUshort(osverlength); stream.WriteString(osver, Encoding.ASCII); stream.WriteUshort(procnamelength); stream.WriteString(procname, Encoding.ASCII); stream.WriteUshort(winsocknamelength); stream.WriteString(winsockname, Encoding.ASCII); stream.WriteUshort(winsockverlength); stream.WriteString(winsockver, Encoding.ASCII); stream.WriteUint(0x00000002); stream.WriteUint(0x00010001); stream.WriteUint(0x00020002); using (TlvBlock tlv = new TlvBlock()) { tlv.WriteByteArray(0x0009, stream.GetBytes()); mainStream.WriteTlvBlock(tlv); } } SNACFunctions.BuildFLAP(Marshal.BuildDataPacket(sess, sh, mainStream)); }
/// <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> /// 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; }
/// <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; }