ICQ-клиент

  • Вид работы:
    Курсовая работа (т)
  • Предмет:
    Информационное обеспечение, программирование
  • Язык:
    Русский
    ,
    Формат файла:
    MS Word
    944,31 Кб
  • Опубликовано:
    2013-07-07
Вы можете узнать стоимость помощи в написании студенческой работы.
Помощь в написании работы, которую точно примут!

ICQ-клиент

Введение

Сегодня Интернет играет очень важную роль в жизни многих людей. Его используют для работы, развлечения, поиска информации, а также знакомства и общения.

В первые годы существования Всемирной паутины пользователи общались преимущественно через электронную почту, но отправлять письма было неудобно и даже нерационально, если оба собеседника одновременно находились в Интернете. Все изменилось, когда появились первые программы мгновенного общения или, менее официально, мессенджеры или интернет-пейджеры.

Эти программы используются для передачи сообщений через Интернет в реальном времени через специальные службы. Если раньше речь шла только о текстовых сообщениях, то теперь с помощью подобных программ можно отсылать и голосовые, и видеосообщения, и файлы, и фотографии.

Как правило, мессенджер скачивается на персональный компьютер и с этого момента начинает составлять достойную конкуренцию электронной почте и даже телефону. Каждый пользователь получает собственный идентификационный номер (или логин), который становится его уникальным именем в Сети.

Программа мгновенного обмена сообщениями (англ. Instant messenger, IM) - программа для обмена сообщениями через интернет в реальном времени через службы мгновенных сообщений (Instant Messaging Service, IMS). С помощью нее могут передаваться текстовые сообщения, звуковые сигналы, изображения, видео, а также производиться такие действия, как совместное рисование или игры. Многие из таких программ могут применяться для организации групповых текстовых чатов или видеоконференций.

Для этого вида коммуникации необходима клиентская программа, так называемый мессенджер (от англ. messenger - курьер). Отличие от электронной почты здесь в том, что обмен сообщениями идёт в реальном времени (англ. instant - мгновенно). Большинство IM-клиентов позволяет видеть, подключены ли в данный момент абоненты, занесённые в список контактов. В ранних версиях программ всё, что печатал пользователь, тут же передавалось. Если он делал ошибку и исправлял её, это тоже было видно. В таком режиме общение напоминало телефонный разговор. В современных программах сообщения появляются на мониторе собеседника уже после окончания редактирования и отправки сообщения.

Как правило, мессенджеры не работают самостоятельно, а подключаются к центральному компьютеру сети обмена сообщениями, называемому сервером. Поэтому мессенджеры и называют клиентами (клиентскими программами). Термин является понятием из клиент-серверных технологий.

Широкому кругу пользователей известно некоторое количество популярных сетей обмена сообщениями, таких, как XMPP, ICQ, MSN, Yahoo!. Каждая из этих сетей разработана отдельной группой разработчиков, имеет отдельный сервер и протоколы, отличается своими правилами и особенностями. Между различными сетями обычно нет никакой взаимосвязи. Таким образом, пользователь сети ICQ не может связаться с пользователем сети MSN. Однако ничто не мешает быть одновременно пользователем нескольких сетей.

Почти для каждой из сетей есть свой мессенджер, разработанный той же командой разработчиков. Так, для пользования вышеуказанными сетями разработчиками предлагаются программы с одноимёнными названиями: ICQ, MSN Messenger, Yahoo! Messenger. Таким образом, если один из адресатов пользуется только сетью ICQ, а другой - только сетью MSN, то можно общаться с ними одновременно, установив на своем компьютере и ICQ, и MSN Messenger, и зарегистрировавшись в обеих сетях.

В качестве альтернативного мессенджера можно выбрать программу стороннего производителя: как коммерческую, так и бесплатную.

Популярными альтернативными программами для общения в сети ICQ являются QIP, Trillian, Miranda IM, Pidgin. Также они позволяют подключаться одновременно к нескольким сетям, что избавляет от необходимости устанавливать отдельный мессенджер для каждой сети и позволяет общаться со всеми адресатами единым образом независимо от сети.

Большинство IM-сетей используют закрытые протоколы, поэтому альтернативные клиенты теоретически могут обладать меньшим количеством базовых функций, чем официальные, хотя на практике чаще бывает наоборот. Однако при изменениях протокола на стороне сервера сети альтернативные клиенты могут внезапно перестать работать (например, подобное явление наблюдалось для «нефирменных» клиентов популярного в России сервиса ICQ).

В качестве альтернативы проприетарным протоколам для IM был разработан открытый протокол XMPP (также известный, как Jabber), используемый в таких сервисах, как Google Talk, Я.Онлайн и др. Этот протокол часто используется для организации общения в корпоративных и других локальных сетях.

1. АНАЛИТИЧЕСКИЙ ОБЗОР ЛИТЕРАТУРЫ

1.1    Анализ предметной области

ICQ основан на протоколе OSCAR, который является протоколом прикладного уровня.

Прикладной уровень - седьмой уровень модели OSI, предназначенный для обеспечения взаимодействия пользователя (процесса-отправителя) с приложениями на удаленном компьютере (процессом-получателем).

Прикладной уровень обеспечивает:

описание форм и методов взаимодействия прикладных процессов;

управление заданиями, передачу файлов, управление системой и т.д.;

идентификацию пользователей по их паролям, адресам и электронным подписям;

определение функционирующих абонентов;

объявление о возможности доступа к новым прикладным процессам;

определение достаточности имеющихся ресурсов;

посылку запросов на соединение с другими прикладными процессами;

управление данными, которыми обмениваются прикладные процессы;

синхронизацию взаимодействия прикладных процессов и др.

Обычно прикладной уровень подразделяется:

на верхний подуровень, включающий сетевые службы; и

на нижний подуровень, содержащий стандартные сервисные элементы, поддерживающие работу сетевых служб.

1.2 Сравнительная характеристика существующих аналогов

На данном этапе существует достаточно большое количество мессенджеров, большинство из которых бесплатны (некоторые в целом бесплатны, но имеют набор дополнительных платных услуг). Ниже приведено описание самых популярных, используемых миллионами пользователей по всему миру. - наиболее распространенный в мире мессенджер с закрытым протоколом. Предоставляет видеосвязь и видеоконференции до 10 человек. Позволяет звонить на обычные телефоны, принимать звонки. Есть версии для мобильных устройств.

MyChat - клиент-серверный мессенджер для локальной сети. Интегрируется с Active Directory, многоуровневый список контактов, доска объявлений, система массовых оповещений, конференции, SSL шифрование трафика, передача оффлайн сообщений и файлов, гибкая система управления правами пользователей, передача файлов и папок.

Google Talk используется как десктоп-клиент и как вэб-дополнение к GMail для текстового чата, аудио и видеосвязи. Совместим с Jabber, AIM и ICQ, а также используется как гаджет для общения с посетителями на сайте.

QIP Infium - быстрый и легкий клиент ICQ, Mail.ru Агент, Я.online, GTalk, SIPNET, LJ Talk с поддержкой различных скинов и плагинов. Поддеррживает видеосвязь и VoIP связь. Можно звонить на обычные и мобильные телефоны по низким тарифам.

Fring - мобильный мультипротокольный клиент для VoIP и видеосвязи, поддерживает Skype, ICQ, Google Talk, MSN Messenger, SIP, twitter, Yahoo! и AIM. Доступен на iPhone, Android, Blackberry, Symbian. Включает сервис IP-телефонии FringOut

AIM Pro - бизнес мессенджер, обеспечивающий высокое качество связи, высокий уровень безопасности и предоставляющий инструменты для совместной работы над приложениями. Интегрируется с Outlook и сервисами Webex для вэб-конференций. Основан на открытой платформе Open AIM и Open Voice. Позволяет звонить на обычные телефоны.

ICQ - очень распространенный на отечественном интернет-пространстве мессенджер с возможностью аудио и видео связи. Работает только под windows. Имеет большое количество плагинов.

Miranda IM - десктоп-клиент, совмещающий в себе несколько ваших аккаунтов в различных системах сообщений (ICQ, AIM, Jabber, MSN ...). Поддержка других мессенджеров обычно реализуется с помощью плагинов.

Zoho Chat - групповой вэб-чат для бизнеса + мультипротокольный web IM + мультиоператорский чат поддержки. Поддерживает Yahoo, AIM, MSN, ICQ, GTalk и Jabber. Умеет пересылать файлы, доставлять оффлайн сообщения, просматривать историю чатов (и искать в ней), чатиться с незарегистрированными в Zoho людьми через браузер, извещать о новых событиях в Zoho-офисе. Позволяет встраивать чат в сайт в виде виджета.

Trillian - мультипротокольный IM-клиент, поддерживает AIM, ICQ, Windows Live Messenger, Yahoo Messenger и IRC. Функции включают групповой чат, аудиочат, SMS, напоминания, шифрование сообщений, поддержка прокси.

1.3 Постановка задачи

Требуется реализовать ICQ-клиент. Выбранный язык программирования - C#, платформа .NET. Пользовательский интерфейс создать при помощи технологии Windows Presentation Foundation.

После успешной авторизации клиент ICQ загружает с сервера список контактов пользователя. Контакты в списке могут быть разделены на группы, имена и количество которых изменяются пользователем.

При добавлении контакта может потребоваться авторизация - разрешение видеть его статус присутствия и отправлять ему файлы. Для таких контактов формируется запрос на авторизацию, который доходит до пользователя добавляемой учётной записи в виде системного уведомления, на которое он может ответить либо согласием, либо отказом, по желанию снабдив решение текстовым комментарием.

С каждым из контактов можно вести личную переписку. Если отправитель не отключил эту возможность, то, в зависимости от клиента, получатель информируется о наборе сообщения, что создаёт эффект присутствия отправителя. Длина отправляемого сообщения ограничена.

В случае, если в момент отправки сообщений адресат не находился в сети, они будут сохранены службой и доставлены адресату, как только тот подключится к сети.

мгновенный обмен сообщение интернет

2. МОДЕЛИ, ПОЛОЖЕННЫЕ В ОСНОВУ ПС

2.1 Функциональные модели

Программное средство разрабатывалось в соответствии со следующими функциональными моделями представленными на рисунках 2.1, 2.2 и 2.3

Рисунок 2.1 Общение с помощью ICQ(IDEF0)

Рисунок 2.2 Посылка сообщения на сервер(IDEF3)

Рисунок 2.3 Посылка сообщения собеседнику(DFD)

.2     
Разработка спецификаций требований к программному средству

Разрабатываемое программное средство может быть использовано в соответствии со следующей диаграммой, представленной на рис. 2.1

К нему предъявляется следующая спецификация требований:

) Программное средство должно быть разработано на платформе .NET с помощью языка программирования C# (Sharp);

) Удобный и понятный интерфейс;

) Минимизация используемых объемов памяти;

) Реализовать хранение истории сообщений;

)Реализовать возможность отправки и получения файлов;

) Размер программного средства не должен превышать 1024 Кб.

Рисунок 2.3 Диаграмма вариантов использования UML

3. Разработка ПРОГРАММНОГО СРЕДСТВА

.1 Обоснование выбора среды разработки

В качестве среды разработки была выбрана IDE Visual Studio 2010 и платформа .NET Framework, сочетающие в себе удобство переносимости и мощь объектно - ориентированного программирования.

Для разработки пользовательского интерфейса была использована платформа Windows Presentation Foundation (WPF). Presentation Foundation (WPF, кодовое название - Avalon) - система для построения клиентских приложений Windows с визуально привлекательными возможностями взаимодействия с пользователем, графическая (презентационная) подсистема в составе .NET Framework (начиная с версии 3.0), имеющая прямое отношение к XAML.

В основе WPF лежит векторная система визуализации, не зависящая от разрешения и созданная с расчетом на возможности современного графического оборудования. WPF предоставляет средства для создания визуального интерфейса, включая Язык XAML (Extensible Application Markup Language), элементы управления, привязку данных, макеты, двухмерную и трехмерную графику, анимацию, стили, шаблоны, документы, текст, мультимедиа и оформление [1].

Графической технологией, лежащей в основе WPF является DirectX, в отличие от Windows Forms, где используется GDI/GDI+[2]. Производительность WPF выше, чем у GDI+ за счёт использования аппаратного ускорения графики через DirectX. представляет собой XML, в котором фактически реализованы классы .NET Framework. Так же реализована модель разделения кода и дизайна, позволяющая кооперироваться программисту и дизайнеру. Кроме того, есть встроенная поддержка стилей элементов, а сами элементы легко разделить на элементы управления второго уровня, которые в свою очередь разлагаются до уровня векторных фигур и свойств/действий.

3.2 Особенности реализации

 - клиент реализован на базе протокола OSCAR.- открытый (с 5 марта 2008 года), но не свободный сетевой протокол, обеспечивающий обмен мгновенными и оффлайновыми текстовыми сообщениями. В данный момент используется для двух систем: AIM (компания AOL, управляемая Time Warner) и ICQ (компания Mail.Ru).

OSCAR. "Open System for Communication in Realtime" (рус. "Открытая система для общения в реальном времени") - внутреннее название проекта (в отличие от внешнего маркетингового названия) используется для определения протокола обмена мгновенными сообщениями. - это низкоуровневый протокол передачи данных, который облегчает разработку высокоуровневых, дейтаграмно-ориентированных слоев по передачи данных. Он использует TCP-соединения между клиентами и серверами.


Байт FLAP-идентификатора всегда 0х2А. FLAP datagram sequence number - используется для выявления ошибок.

FLAP channel - это идентификатор, используемый для определения различных типов данных во FLAP-пакете, для передачи данных через один и тот же TCP-сокет. В некотором роде это аналог TCP/UPD номеров портов. В OSCAR используются пять видов каналов:

x01 - договор о новом соединении;

х02 - SNAC-пакет;

х03 - ошибка FLAP-уровня;

х04 - договор о завершении соединения;

х05 - оставаться в сети.

Наиболее часто используется канал 0х02, так как только по нему могут передаваться SNAC-пакеты.

SNAC - это базовый модуль передачи данных между клиентом и сервером. SNAC-слой находится выше FLAP-слоя, он является содержимым поля данных FLAP-а, передается только по каналу 0х02. Формат SNAC:


Нет никакой информации о длине данных в SNAC. Она должна быть определена из заголовка FLAP-а.Флаги являются одним из главных свойств пакета данных. Например, первый бит двухбайтового флага устанавлявается, если да данного id запроса было послано более одного SPAC.

TLV (type-length-value - тип-длина-значение) - очень удобный и эффективный метод для передачи данных в организованном формате, особенно строк переменной длины. 16 бит кода типа, 16 бит значения длины данных, сами данные:

TLV-блоки могут находиться внутри SNAC-блоков, но это не обязательно. Иногда их располагают непосредственно во FLAP-поле с данными, но чаще внутри SNAC. TLV-блоков в SNAC может быть несколько. Введение этих блоков было большим прорывом, ведь стало удобно посылать несколько строк или значений различной длины одним пакетом, например как {0x0011, 0x000c, "afritz@iname.com"}.

3.3 Разработка программной архитектуры

Сам проект состоит из двух подпроектов: Core и ICQLite. Первый отвечает за базовые функции ICQ, авторизацию, передачу данных и прочую бизнес-логику. ICQLite - содержит классы и окна, используемые для построения пользовательского интерфейса.

.3.1 Core

Основной класс - Session, представляет собой ICQ сессию. Он агрегирует в себе классы-менеджеры ConnectionManager, SSIManager, MessageManager, StatusManager, и т.д. Ниже будут рассмотрены некоторые из них. Класс содержит методы InitializeLogger, Logon, Logoff, AddBuddy, RemoveBuddy, ActivateBuddyList, SendAuthorizationRequest и многие другие (все они располагаются в папке ObjectManagers проекта), которые далее оперируют с методами менеджеров. Также в нем имеются множество событий, которые срабатывают при происхождении каких-либо действий, на которые можно назначить обработчики событий из пользовательского интерфейса для его обновления.

AuthorizationManager - отвечает за авторизацию, содержит методы LoginToService, ProcessIncomingPacket, SendAuthorizationRequest, ProcessLoginResponse и др. - класс, отвечающий за установку соединения с сервером. Содержит методы CreateNewConnection, DeregisterConnection, CreateNewChatConnection, CreateNewFileTransferConnection, RemoveChatConnection и многие другие.

Если рассмотреть подробнее методы классов-менеджеров, то можно заметить, что во многих происходит построение TLV-блоков с данными, которые потом обворачиваются в SNAC-пакеты и отправляются на сервер.

Различные SNAC-и описаны как классы в папке SNACs, также там представлены методы работы с ними.

Класс Logging отвечает за логгирование поступивших и отправленных пакетов, что намного упрощает разработку и отладку проекта.

Также имеются классы с описанием делегатов для событий и аргументов различных событий.

3.3.2 ICQLite

В данном подпроекте реализован пользовательский интерфейс приложения. В нем используется концепция событийно-ориентированного программирования. Это значит, что в коде явным образом выделяется главный цикл программы, тело которого состоит из двух основных частей: выборки события и обработки события. Понятно, что недопустимы для приложения длительные выполнения обработчиков событий, поэтому многие операции выполняются в фоновом потоке. Но тут встает проблема обновления пользовательского интерфейса результатами обработки, ведь технология WPF не позволяет изменять UI из потоков, не являющихся основным. Решение - ставить обработчики событий в очередь на выполнение главному потоку методом Dispatcher.Invoke(…).

Первое окно, видимое пользователю при запуске приложения - класса LoginWindow, в нем имеются поля для ввода номера ICQ и пароля, в нем же происходит отправка на сервер этих данных. При успешно прошедшей авторизации это окно загружает окно с контактами класса ContactListWindow, а само закрывается.

ContactListWindow отображает контакты, расформированные по группам, в виде дерева элементов. В главном меню окна имеется возможность добавить контакт - за это отвечает окно AddContactWindow. Каждый контакт из списка контактов имеет контекстное меню, в нем присутствуют опции отображения информации о контакте (AboutWindow) и удаления контакта из серверного списка контактов.

При двойном щелчке на контакте открывается окно с чатом для данного контакта. При повторном двойном щелчке на нем же - то же самое окно повторно выходит на передний план.

ChatWindow. Имееет RichTextBox для ввода текста, а сама переписка отображается выше, с датой отправки сообщения. CheckBox внизу позволяет управлять отправкой сообщения по нажатию клавиши Enter, либо по нажатию кнопки “Send”.

Если окно ChatWindow c перепиской с определенным контактом не было открыто, либо было закрыто, а этот контакт отправил сообщение пользователю, то напротив него в списке контактов отображается значок в виде сообщения, по нажатию на который он пропадает, и открывается окно с чатом.

        
ТЕСТИРОВАНИЕ ПРОГРАММНОГО СРЕДСТВА

Для данного программного средства было использовано и функциональное тестирование:

Тестовые сценарии приведены в таблице 1.

Таблица 1 - Тестовые сценарии

Название модуля

Последовательность действий

Ожидаемый результат

1

Авторизация

1. Заполнить обязательные поля на форме авторизации 2. Нажать на кнопку авторизации

1. Проверить наличие проверки на обязательные поля 2. Проверить факт авторизации

2

Добавление контакта

1. Заполнить поля на форме 2. Нажать на кнопку добавления

1. Проверить удалось ли добавить новый контакт

3

Список контактов

1. Удалить контакт

1. Проверить удален ли контакт.

4

Список контактов

1. Посмотреть информацию о контакте

1. Проверить достоверность информации о контакте

5

Чат

1. Отправить сообщение для пользователя, находящегося онлайн

1. Проверить дошло ли сообщение до собеседника 2. Проверить достоверность дошедшего сообщения

6

Чат

1. Отправить сообщение для пользователя, находящегося оффлайн

1 Проверить дошло ли сообщение до собеседника 2 Проверить достоверность дошедшего сообщения

7

Чат

1. Отправить сообщение другим контактом для контакта, находящегося онлайн

1 Проверить дошло ли сообщение до контакта 2 Проверить достоверность дошедшего сообщения

7

Чат

1. Отправить сообщение другим контактом для контакта, находящегося оффлайн

1 Проверить дошло ли сообщение до контакта 2 Проверить достоверность дошедшего сообщения


        
МЕТОДИКА РАБОТЫ С ПРОГРАММНЫМ СРЕДСТВОМ

Login-форма cодержит поля для ввода логина (ICQ номера), пароля.

 

Рисунок 4.1Login - форма

По нажатию кнопки “Sign In” происходит отправка данных на сервер, выполняется авторизация пользователя в сети. При неудаче выводится сообщение о типе ошибки.

Также обновляется статус и проценты выполненной на сервере работы по авторизации:

 

Рисунок 4.2Статус авторизации

 

Рисунок 4.3 Общий вид программы

Контакты отображаются по названиям групп, внутри них - списки контактов, зеленый индификатор - контакт находится в сети, красный - оффлайн. Двойным щелчком по контакту открывается окно чата.

В окне чата реализована поддержка оффлайн сообщений (отображаются серым цветом). Есть форма для ввода текста, и форма для отображения переписки. Также можно включить отсылку сообщения по нажатию клавиши Enter.

Если окно чата закрыто, а сообщение от собеседника пришло, в списке контактов отображается значок письма. По двойному щелчку окно с чатом открывается, а он пропадает (заменяется на онлайн/оффлайн значок).

Рисунок 4.4Окно чата

Рисунок 4.5 Общий вид программы (Пришло сообщение)

 

Рисунок 4.5 Информация о пользователе

Добавление контакта идет в отдельном окне, после контакт лист заново перерисовывается. Удаление происходит при выборе данной опции из контекстного меню контакт-листа, после чего он также заново перерисовывается.

Рисунок 4.6 Добавление контакта

ЗАКЛЮЧЕНИЕ

В результате выполнения данной курсовой работы был получен программный продукт, названный "ICQLite". Было проведено исследование .NET Framework, которая использовалась при создании программного средства, а также протокола OSCAR.

В результате проделанной работы были усвоены основные приемы и навыки объектно-ориентированного программирования с использованием языка программирования высокого уровня C#. Применялись такие базовые концепции как: наследование, полиморфизм, инкапсуляция.

Программа реализует cредство мгновенного обмена сообщениями (англ. Instant messenger, способ обмена сообщениями через Интернет в реальном времени через службы мгновенных сообщений (Instant Messaging Service, IMS))

СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ

[1] Крупник А. Изучаем С#. Питер, 2001. - 480 c.

[2] Глинн Д. Платформа .NET 3.0 для профессионалов, 2008. - 1024c.

[3] Агуров П.В. C#. Сборник рецептов М.: ООО «Бином-Пресс», 2006. - 512

[4] Шилдт Г. C#: учебный курс, 2007. - 768 c.

[5] Джейсон П. Visual C# 2.0. NET Полное руководство. СПб. : Питер Ком, 2004. - 288 с.

[6] Фролов А., Фролов Г. C#. Визуальное проектирование приложений. М.: ООО «Бином-Пресс», 2006. - 512 c.

[7] Кариев Ч.А. Разработка Windows-приложений на основе Visual C#, 2005. 1000 c.

[8] Буч Г. Объектно-ориентированный анализ и проектирование. Диалог-МИФИ, 2006. - 800 c.

[9] Бадд Т. Объектно-ориентированное программирование в действии. Диалог-МИФИ, 2005. - 650 c.

[10] Виейра Р. Программирование баз данных. Диалог-МИФИ, 2005. - 1020

ПРИЛОЖЕНИЕ А


ЛИСТИНГ ПРОГРАММНОГО СРЕДСТВА

System;System.Collections;System.IO;System.Security.Cryptography;System.Text;csammisrun.OscarLib.Utility;

csammisrun.OscarLib

{

#region Logged in / out exceptions

/// <summary>

/// Thrown when an operation is requested that requires the <see cref="Session"/>

/// to be logged in

/// </summary>class NotLoggedInException : Exception

{

}

/// <summary>

/// Thrown when an operation is requested that requires the <see cref="Session"/>

/// to be logged out

/// </summary>class LoggedInException : Exception

{readonly string _message;

/// <summary>

/// Creates a new LoggedInException with a blank message

/// </summary>LoggedInException()

{

_message = "";

}

/// <summary>

/// Creates a new LoggedInException

/// </summary>

/// <param name="message">The message to be passed with the exception</param>LoggedInException(string message)

{

_message = message;

}

/// <summary>

/// Gets a message that describes the current exception

/// </summary>override string Message

{{ return _message; }

}

}

#endregion

/// <summary>

/// The representation of an AOL Instant Messenger or ICQ session

/// </summary>class Session

{readonly OSCARIdentification _clientid = new OSCARIdentification();readonly string _password;readonly Hashtable _requestidstorage = new Hashtable();readonly AuthorizationManager authManager;readonly ChatRoomManager chatRoomManager;readonly ConnectionManager connectionManager;readonly PacketDispatcher dispatcher = new PacketDispatcher();readonly FamilyManager familyManager = new FamilyManager();readonly GraphicsManager graphicsManager;readonly IcqManager icqManager;readonly LimitManager limitManager = new LimitManager();readonly MessageManager messageManager;readonly RateClassManager rateManager;readonly SearchManager searchManager;readonly ServiceManager serviceManager;readonly SSIManager ssiManager;readonly StatusManager statusManager;

Capabilities _caps = Capabilities.OscarLib;bool _loggedin;ushort _loginport = 5190;ushort _parametercount;PrivacySetting _privacy;bool _publicidletime;string _screenname;

/// <summary>

/// Create a new OSCAR session

/// </summary>

/// <param name="screenname">The screenname to log in</param>

/// <param name="password">The password associated with the screenname</param>

/// <exception cref="ArgumentException">Thrown when <paramref name="screenname"/> is not

/// a valid AIM or ICQ screenname.</exception>Session(string screenname, string password)

{

// Check to make sure the screenname is something valid(!ScreennameVerifier.IsValidAIM(screenname) &&

!ScreennameVerifier.IsValidICQ(screenname))

{new ArgumentException(screenname + " is not a valid AIM or ICQ screenname", "screenname");

}

// Save parameter values

_screenname = screenname;

_password = password;

= new ConnectionManager(this);= new ServiceManager(this);= new SSIManager(this);= new IcqManager(this);= new MessageManager(this);= new StatusManager(this);= new ChatRoomManager(this);= new GraphicsManager(this);= new AuthorizationManager(this);= new SearchManager(this);= new RateClassManager(this);

.CreateNewConnection(0x0017);

// Create a default set of capabilities for this session();

// Set up some default values for public properties

_publicidletime = true;

// Set initial values for internal properties

_loggedin = false;

_privacy = PrivacySetting.AllowAllUsers;

_parametercount = 0;

}

#region Public methods

/// <summary>

/// Sets the session's <see cref="ClientIdentification"/> to the AOL defaults

/// </summary>

/// <exception cref="LoggedInException">Thrown when the <see cref="Session"/> is already logged in</exception>void SetDefaultIdentification()

{(LoggedIn)

{new LoggedInException("Identification cannot be changed after the session is logged in");

}

_clientid.ClientName = Constants.CLIENT_NAME;

_clientid.ClientId = Constants.CLIENT_ID;

_clientid.ClientMajor = Constants.CLIENT_MAJOR;

_clientid.ClientMinor = Constants.CLIENT_MINOR;

_clientid.ClientLesser = Constants.CLIENT_LESSER;

_clientid.ClientBuild = Constants.CLIENT_BUILD;

_clientid.ClientDistribution = Constants.CLIENT_DISTRIBUTION;

}

/// <summary>

/// Initialize the logging system

/// </summary>

/// <param name="baseDir">The directory in which to save log files</param>

/// <returns>The full logfile path</returns>string InitializeLogger(string baseDir)

{

// Initialize the logging systemcurrentTime = DateTime.Now;logfileName = String.Empty;

+= ScreenName + "_";+= currentTime.Year.ToString("0000") + "-" + currentTime.Month.ToString("00") + "-" +.Day.ToString("00") + "_";+= currentTime.Hour.ToString("00") + "." + currentTime.Minute.ToString("00") + "." +.Second.ToString("00") + ".";+= currentTime.Millisecond.ToString("000") + "_";+= "OscarLib.log";

logFilePath = Path.Combine(baseDir, logfileName);(!Directory.Exists(Path.GetDirectoryName(logFilePath)))

{.CreateDirectory(Path.GetDirectoryName(logFilePath));

}

.sw = new StreamWriter(logFilePath);

logFilePath;

}

/// <summary>

/// Begins the process of logging in to the OSCAR service

/// </summary>

/// <param name="loginserver">The OSCAR login server</param>

/// <param name="port">The OSCAR service port</param>

/// <remarks>

/// <para>

/// This function is non-blocking, because the login process does not happen

/// instantly. The OSCAR library will raise the <see cref="Session.LoginCompleted"/> event

/// when the login process has finished successfully.

/// </para>

/// <para>

/// The OSCAR library raises periodic status update events throughout the login process

/// via the <see cref="Session.StatusUpdate"/> event.

/// </para>

/// <para>

/// Errors may occur during the login process; if an error occurs, the OSCAR library raises

/// the <see cref="Session.ErrorMessage"/> event, and stops the remaining login sequence.

/// </para>

/// </remarks>

/// <exception cref="LoggedInException">Thrown when the <see cref="Session"/> is already logged in</exception>void Logon(string loginserver, int port)

{(LoggedIn)

{new LoggedInException();

}

= false;.LoginToService(loginserver, port);("Connecting...", 0.00);

}

/// <summary>

/// Disconnects all active OSCAR connections and resets the session

/// </summary>void Logoff()

{= false;

(Connection conn in connectionManager.UniqueConnections())

{.DisconnectFromServer(false);

}

}

/// <summary>

/// Adds a buddy to the client's server-side buddy list

/// </summary>

/// <param name="screenname">The screenname of the buddy to add</param>

/// <param name="parentID">The ID of the parent group of the buddy</param>

/// <param name="index">The index of the buddy in the group</param>

/// <param name="alias">The alias of the buddy ("" for none)</param>

/// <param name="email">The email address of the buddy ("" for none)</param>

/// <param name="comment">The comment to be stored for the buddy ("" for none)</param>

/// <param name="SMS">The SMS number for the buddy ("" for none)</param>

/// <param name="soundfile">The soundfile for the buddy ("" for none)</param>

/// <param name="authorziationRequired"><c>true</c> if we require authorization for this buddy, <c>false</c> otherwise</param>

///<param name="authorizationReason">The authorization reason/message that will be send to the client</param>

/// <exception cref="NotLoggedInException">Thrown when the <see cref="Session"/> is not logged in</exception>

/// <remarks>This function will probably not remain here; the SSI Manager will be made public</remarks>

[Obsolete(

"This method is obsolete and will be removed soon. Use the overloaded AddBuddy method without the index parameter."

)]void AddBuddy(string screenname, ushort parentID, int index, string alias, string email, string comment,SMS, string soundfile, bool authorziationRequired, string authorizationReason)

{(!LoggedIn)

{new NotLoggedInException();

}

.AddBuddy(screenname, parentID, index, alias, email, SMS, comment, soundfile, authorziationRequired,);

}

/// <summary>

/// Adds a buddy to the client's server-side buddy list

/// </summary>

/// <param name="screenname">The screenname of the buddy to add</param>

/// <param name="parentID">The ID of the parent group of the buddy</param>

/// <param name="alias">The alias of the buddy ("" for none)</param>

/// <param name="email">The email address of the buddy ("" for none)</param>

/// <param name="comment">The comment to be stored for the buddy ("" for none)</param>

/// <param name="SMS">The SMS number for the buddy ("" for none)</param>

/// <param name="soundfile">The soundfile for the buddy ("" for none)</param>

/// <param name="authorziationRequired"><c>true</c> if we require authorization for this buddy, <c>false</c> otherwise</param>

/// <exception cref="NotLoggedInException">Thrown when the <see cref="Session"/> is not logged in</exception>

/// <remarks>This function will probably not remain here; the SSI Manager will be made public</remarks>void AddBuddy(string screenname, ushort parentID, string alias, string email, string comment,SMS, string soundfile, bool authorziationRequired, string authorizationReason)

{(!LoggedIn)

{new NotLoggedInException();

}

.AddBuddy(screenname, parentID, alias, email, SMS, comment, soundfile, authorziationRequired,);

}

/// <summary>

/// Moves a buddy

/// </summary>

/// <param name="buddyID">The ID of the buddy to move</param>

/// <param name="parentID">The ID of the destination group</param>

/// <param name="index">The index in the destination group to move to</param>void MoveBuddy(ushort buddyID, ushort parentID, int index)

{(!LoggedIn)

{new NotLoggedInException();

}

.MoveBuddy(SSI.GetBuddyByID(buddyID, parentID), SSI.GetGroupByID(parentID), index);

}

/// <summary>

/// Remove a buddy

/// </summary>

/// <param name="buddyID">The ID of the buddy to remove</param>void RemoveBuddy(ushort buddyID, ushort parentID)

{(!LoggedIn)

{new NotLoggedInException();

}buddy = SSI.GetBuddyByID(buddyID, parentID);(buddy != null).RemoveBuddy(buddy);

}

/// <summary>

/// Adds a group to the client's server-side buddy list

/// </summary>

/// <param name="groupname">The name of the new group</param>

/// <param name="index">The index into the current list of groups</param>

[Obsolete(

"This method is obsolete and will be removed soon. Use the overloaded AddGroup methods without the index parameter."

)]void AddGroup(string groupname, int index)

{(!LoggedIn)

{new NotLoggedInException();

}

.AddGroup(groupname, index);

}

/// <summary>

/// Adds a group to the client's server-side buddy list

/// </summary>

/// <param name="groupname">The name of the new group</param>

/// <param name="id">The group id</param>void AddGroup(string groupname, ushort id)

{(!LoggedIn)

{new NotLoggedInException();

}

.AddGroup(groupname, id);

}

/// <summary>

/// Adds a group to the client's server-side buddy list

/// </summary>

/// <param name="groupname">The name of the new group</param>void AddGroup(string groupname)

{(!LoggedIn)

{new NotLoggedInException();

}

.AddGroup(groupname);

}

/// <summary>

/// Adds the master group. This is necessary if a contact list is empty to add further groups after

/// </summary>

/// <param name="groupname">The master group name</param>void AddMasterGroup(string groupname)

{(!LoggedIn)

{new NotLoggedInException();

}(groupname, (ushort) 0);

}

/// <summary>

/// Move a group in the buddy list

/// </summary>

/// <param name="groupID">The ID of the group to move</param>

/// <param name="index">The new index of the group</param>void MoveGroup(ushort groupID, int index)

{(!LoggedIn)

{new NotLoggedInException();

}

.MoveGroup(SSI.GetGroupByID(groupID), index);

}

/// <summary>

/// Remove a group from the server-side buddy list

/// </summary>

/// <param name="groupID">ID of the group to remove</param>void RemoveGroup(ushort groupID)

{(!LoggedIn)

{new NotLoggedInException();

}group = SSI.GetGroupByID(groupID);(group != null).RemoveGroup(group);

}

/// <summary>

/// Tells AIM to begin sending UserStatus objects to client (online or away)

/// Client should call in response to <see cref="ContactListFinished"/> event

/// </summary>void ActivateBuddyList()

{.ActivateSSI(this);();

}

/// <summary>

/// Requests a list of user interests from the server

/// </summary>

/// <exception cref="NotLoggedInException">Thrown when the <see cref="Session"/> is not logged in</exception>void RequestInterestsList()

{(!LoggedIn)

{new NotLoggedInException();

}F.RequestInterestList(this);

}

/// <summary>

/// Sends an icq authorization request

/// </summary>

/// <param name="screenname">the destination screenname</param>

/// <param name="reason">the request reason</param>void SendAuthorizationRequest(string screenname, string reason)

{(!LoggedIn)

{new NotLoggedInException();

}

// TODO reason string works only with ASCII encoding until now.SendAuthorizationRequest(this, screenname, reason);

}

/// <summary>

/// Sends an icq authorization response

/// </summary>

/// <param name="screenname">the destination screenname</param>

/// <param name="grantAuthorization">true, if the authorization should be granted, otherwise false</param>

/// <param name="reason">the reason for the decision</param>void SendAuthorizationResponse(string screenname, bool grantAuthorization, string reason)

{(!LoggedIn)

{new NotLoggedInException();

}.SendAuthorizationResponse(this, screenname, grantAuthorization, reason);

}

/// <summary>

/// Grants the authorization to another screenname for the future

/// </summary>

/// <param name="screenname">The uin/screenname</param>

/// <param name="reason">The reason message</param>

/// <remarks>TODO ... seems to be obsolete in the current Oscar version</remarks>void SendFutureAuthorizationGrant(string screenname, string reason)

{(!LoggedIn)

{new NotLoggedInException();

}.SendFutureAuthorizationGrant(this, screenname, reason);

}

/// <summary>

/// Sends a requests for the server side buddylist. Server should reply with

/// the buddylist, or with the info that the client side buddylist is up to date

/// <remarks>TODO have to be tested</remarks>

/// </summary>void SendContactListCheckout()

{(LastModificationDate);

}

/// <summary>

/// Sends a requests for the server side buddylist. Server should reply with

/// the buddylist, or with the info that the client side buddylist is up to date

/// </summary>

/// <param name="lastModificationDate">the date when the client side buddylist was updated the last time</param>

/// <remarks>TODO have to be tested</remarks>void SendContactListCheckout(DateTime lastModificationDate)

{(!LoggedIn)

{new NotLoggedInException();

}localSSIItemCount = SSI.GetLocalSSIItemCount();.SendContactListCheckout(this, LastModificationDate, true, localSSIItemCount);

}

#region File transfer methods

/// <summary>

/// Send a file to a remote client via a direct connection

/// </summary>

/// <param name="recipient">The screenname of the remote client</param>

/// <param name="filename">The path of the file to send</param>

/// <returns>A key with which to reference this file transfer, or "" if a warning was

/// generated during the initialization process</returns>

/// <exception cref="NotLoggedInException">Thrown when the <see cref="Session"/> is not logged in</exception>Cookie SendFile(string recipient, string filename)

{(!LoggedIn)

{new NotLoggedInException();

}

ftconn =.CreateNewFileTransferConnection(DirectConnectionMethod.Direct, DirectConnectRole.Initiator);.Other.ScreenName = recipient;.LocalFileName = filename;.ConnectToServer();ftconn.Cookie;

}

/// <summary>

/// Start a DirectIM session with a remote client via a direct connection

/// </summary>

/// <param name="recipient">The screenname of the remote client</param>

/// <param name="message">A message with which to invite the remote client</param>

/// <returns>A key with which to reference this DirectIM session, or "" if a warning was

/// generated during the initialization process</returns>

/// <exception cref="NotLoggedInException">Thrown when the <see cref="Session"/> is not logged in</exception>Cookie StartDirectIM(string recipient, string message)

{(!LoggedIn)

{new NotLoggedInException();

}

dimconn =.CreateNewDirectIMConnection(DirectConnectionMethod.Direct, DirectConnectRole.Initiator);.Other.ScreenName = recipient;.Message = message;.ConnectToServer();dimconn.Cookie;

}

/// <summary>

/// Send a file to a remote client via an AOL proxy

/// </summary>

/// <param name="recipient">The screenname of the remote client</param>

/// <param name="filename">The path of the file to send</param>

/// <returns>A key with which to reference this file transfer, or "" if a warning was

/// generated during the initialization process</returns>

/// <exception cref="NotLoggedInException">Thrown when the <see cref="Session"/> is not logged in</exception>Cookie SendFileProxied(string recipient, string filename)

{(!LoggedIn)

{new NotLoggedInException();

}newconn =.CreateNewFileTransferConnection(DirectConnectionMethod.Proxied, DirectConnectRole.Initiator);.Other.ScreenName = recipient;.LocalFileName = filename;.ConnectToServer();newconn.Cookie;

}

/// <summary>

/// Start a DirectIM session with a remote client via an AOL proxy

/// </summary>

/// <param name="recipient">The screenname of the remote client</param>

/// <param name="message">A message with which to invite the remote client</param>

/// <returns>A key with which to reference this DirectIM session, or "" if a warning was

/// generated during the initialization process</returns>

/// <exception cref="NotLoggedInException">Thrown when the <see cref="Session"/> is not logged in</exception>Cookie StartDirectIMProxied(string recipient, string message)

{(!LoggedIn)

{new NotLoggedInException();

}

dimconn =.CreateNewDirectIMConnection(DirectConnectionMethod.Proxied, DirectConnectRole.Initiator);.Other.ScreenName = recipient;.Message = message;.ConnectToServer();dimconn.Cookie;

}

/// <summary>

/// Accept an invitation to a DirectIM session

/// </summary>

/// <param name="key">The key received in the <see cref="OscarLib_DirectIMRequestReceived"/> event</param>void AcceptDirectIMSession(Cookie key)

{(!LoggedIn)

{new NotLoggedInException();

}

conn = Connections.GetDirectConnectionByCookie(key) as DirectIMConnection;(conn != null)

{.ConnectToServer();

}

{new Exception("Invalid DirectIM session key: \"" + key + "\"");

}

}

/// <summary>

/// Accept a file being sent to the client

/// </summary>

/// <param name="key">The key received in the <see cref="FileTransferRequestReceived"/> event</param>

/// <param name="savelocation">The path to which to save the file</param>

/// <exception cref="NotLoggedInException">Thrown when the <see cref="Session"/> is not logged in</exception>

/// <exception cref="System.Exception">Thrown when <paramref name="key"/> is not a valid file transfer key</exception>void AcceptFileTransfer(Cookie key, string savelocation)

{(!LoggedIn)

{new NotLoggedInException();

}

conn = Connections.GetDirectConnectionByCookie(key) as FileTransferConnection;(conn != null)

{.LocalFileName = savelocation;.ConnectToServer();

}

{new Exception("Invalid file transfer key: \"" + key + "\"");

}

}

/// <summary>

/// Cancel a pending or in-progress file transfer

/// </summary>

/// <param name="key">The key received with the transfer request</param>

/// <exception cref="NotLoggedInException">Thrown when the <see cref="Session"/> is not logged in</exception>

/// <exception cref="System.Exception">Thrown when <paramref name="key"/> is not a valid file transfer key</exception>void CancelFileTransfer(Cookie key)

{(!LoggedIn)

{new NotLoggedInException();

}

conn = Connections.GetDirectConnectionByCookie(key) as FileTransferConnection;(conn != null)

{.CancelFileTransfer("User cancelled transfer");

}

}

/// <summary>

/// Cancel a pending or in-progress Direct IM session

/// </summary>

/// <param name="key">The key received with the connection request</param>

/// <exception cref="NotLoggedInException">Thrown when the <see cref="Session"/> is not logged in</exception>

/// <exception cref="System.Exception">Thrown when <paramref name="key"/> is not a valid file transfer key</exception>void CancelDirectIMSession(Cookie key)

{(!LoggedIn)

{new NotLoggedInException();

}

conn = Connections.GetDirectConnectionByCookie(key) as DirectIMConnection;(conn != null)

{.SendDirectConnectionCancellation(conn, "User cancelled Direct Connection");.DisconnectFromServer(false);

}

}

#endregion

#endregion

#region Internal methods

/// <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>internal byte[] HashPassword(byte[] authkey)

{md5 = new MD5CryptoServiceProvider();

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

}

/// <summary>

/// Stores data associated with a SNAC request/reply

/// </summary>

/// <param name="requestid">A SNAC request ID</param>

/// <param name="data">The data to be stored</param>internal void StoreRequestID(uint requestid, object data)

{

_requestidstorage.Add(requestid, data);

}

/// <summary>

/// Retrieves data associated with a SNAC request/reply

/// </summary>

/// <param name="requestid">A SNAC request ID</param>

/// <returns>The data previously stored by <see cref="StoreRequestID"/></returns>internal object RetrieveRequestID(uint requestid)

{_requestidstorage[requestid];

}

/// <summary>

/// Sets the session's privacy setting sent by the server in SNAC(13,06)

/// </summary>

/// <param name="ps">One of the <see cref="PrivacySetting"/> enumeration members</param>internal void SetPrivacyFromServer(PrivacySetting ps)

{

_privacy = ps;

}

/// <summary>

/// Sets whether or not the client's idle time is public -- SNAC(13,06)

/// </summary>

/// <param name="publicidletime">true if others can see this client's idle time, false otherwise</param>internal void SetPresence(bool publicidletime)

{

_publicidletime = publicidletime;

}

/// <summary>

/// Keeps track of the SNAC parameter responses that have been received thus far

/// </summary>internal void ParameterSetArrived()

{

_parametercount++;

(_parametercount == 5)

{

// We can send more stuff now

}

}

#endregion

#region Properties

#region Connection properties

ProxyType proxySetting = ProxyType.None;

/// <summary>

/// The username to use for a proxy server

/// </summary>string ProxyUsername { get; set; }

/// <summary>

/// The password to use for a proxy server

/// </summary>string ProxyPassword { get; set; }

/// <summary>

/// The proxy server to connect through

/// </summary>string ProxyServer { get; set; }

/// <summary>

/// The port to connect to on the proxy server

/// </summary>int ProxyPort { get; set; }

/// <summary>

/// The <see cref="ProxyType"/> to use for this connection

/// </summary>ProxyType ProxySetting

{{ return proxySetting; }{ proxySetting = value; }

}

#endregion Connection propertiesEncoding encoding;

/// <summary>

/// Gets or sets the screen name associated with this session

/// </summary>

/// <remarks>

/// The screen name cannot be set by this property while the client is offline.

/// When the client is online, setting the screen name by this property changes the

/// screen name's formatting on the server.

/// </remarks>

/// <exception cref="ArgumentException">Thrown when <paramref name="screenname"/> is not

/// a valid AIM or ICQ screenname.</exception>string ScreenName

{{ return _screenname; }

{(LoggedIn)

{new ArgumentException(value + " is not a valid AIM or ICQ screenname");

}

_screenname = value;

// TODO: Actually reset the formatting...

}

}

}

/// <summary>

/// Gets or sets the port number used for OSCAR logins

/// </summary>

/// <remarks>

/// Traditionally, this is port 5190; however, AIM 6 has been caught using port 443 to negotiate

/// connections with login.oscar.aol.com and ars.oscar.aol.com. Future versions of OscarLib may use

/// this property to support login via port 443.

/// </remarks>ushort LoginPort

{{ return _loginport; }set { _loginport = value; }

}

/// <summary>

/// Gets or sets this session's OSCAR identification information

/// </summary>

/// <exception cref="LoggedInException">Thrown when the <see cref="Session"/> is already logged in</exception>OSCARIdentification ClientIdentification

{{ return _clientid; }

}

/// <summary>

/// Gets or sets the OSCAR capabilities associated with the session

/// </summary>

/// <remarks>

/// The client capabilities must be set before the session is logged in because the

/// client's capabilities are communicated during the login process and are kept through

/// the session.

/// </remarks>

/// <exception cref="LoggedInException">Thrown when the <see cref="Session"/> is already logged in</exception>Capabilities ClientCapabilities

{{ return _caps; }

{(LoggedIn)

{new LoggedInException("Client capabilities cannot be set after the session is logged in");

}

_caps = value;((value & Capabilities.UTF8) == Capabilities.UTF8)

{= Encoding.UTF8;

}

{= Encoding.ASCII;

}

}

}

/// <summary>

/// Gets the recommended enocding format depending on the client capability settings

/// </summary>Encoding Encoding

{{ return encoding; }

}

/// <summary>

/// Gets a value indicating whether this client has completed the login process

/// </summary>bool LoggedIn

{{ return _loggedin; }set { _loggedin = value; }

}

/// <summary>

/// Gets the <see cref="SSIManager"/> associated with this session

/// </summary>SSIManager SSI

{{ return ssiManager; }

}

/// <summary>

/// Gets the <see cref="LimitManager"/> associated with this session

/// </summary>LimitManager Limits

{{ return limitManager; }

}

/// <summary>

/// Gets the <see cref="IcqManager"/> associated with this session

/// </summary>IcqManager ICQ

{{ return icqManager; }

}

/// <summary>

/// Gets the <see cref="MessageManager"/> associated with this session

/// </summary>MessageManager Messages

{{ return messageManager; }

}

/// <summary>

/// Gets the <see cref="ChatRoomManager"/> associated with this session

/// </summary>ChatRoomManager ChatRooms

{{ return chatRoomManager; }

}

/// <summary>

/// Gets the <see cref="GraphicsManager"/> associated with this session

/// </summary>GraphicsManager Graphics

{{ return graphicsManager; }

}

/// <summary>

/// Gets the <see cref="StatusManager"/> associated with this session

/// </summary>StatusManager Statuses

{{ return statusManager; }

}

/// <summary>

/// Gets the <see cref="SearchManager"/> associated with this session

/// </summary>SearchManager Searches

{{ return searchManager; }

}

/// <summary>

/// Gets or sets a filesystem path where OscarLib can place received data

/// </summary>

/// <remarks>During an OSCAR Direct Connect session, "transient" files may come over the wire.

/// If ScratchPath is set to a valid path, OscarLib will save the files locally and return

/// <see cref="System.IO.FileStream"/> references to the objects. Otherwise, the files will

/// be returned as <see cref="System.IO.MemoryStream"/> objects, which will take more active memory.</remarks>string ScratchPath { get; set; }

/// <summary>

/// Gets the <see cref="ConnectionManager"/> associated with this session

/// </summary>ConnectionManager Connections

{{ return connectionManager; }

}

/// <summary>

/// Gets the <see cref="ServiceManager"/> associated with this session

/// </summary>ServiceManager Services

{{ return serviceManager; }

}

/// <summary>

/// Gets the <see cref="PacketDispatcher"/> associated with this session

/// </summary>PacketDispatcher Dispatcher

{{ return dispatcher; }

}

/// <summary>

/// Gets the <see cref="FamilyManager"/> associated with this session

/// </summary>FamilyManager Families

{{ return familyManager; }

}

/// <summary>

/// Gets the <see cref="RateClassManager"/> associated with this session

/// </summary>RateClassManager RateClasses

{{ return rateManager; }

}

/// <summary>

/// Gets the <see cref="AuthorizationManager"/> associated with this session

/// </summary>AuthorizationManager Authorization

{{ return authManager; }

}

#endregion

/// <summary>

/// Gets or Sets the last modification date and time of the buddylist

/// </summary>DateTime LastModificationDate { get; set; }

#region Public events and protected event firing functions

#region OscarLib-generated events

/// <summary>

/// Occurs when an unhandled exception is raised in the course of dispatching and processing a packet

/// </summary>event PacketDispatchExceptionHandler PacketDispatchException;

/// <summary>

/// Raises the <see cref="PacketDispatchException"/> event

/// </summary>internal void OnPacketDispatchException(Exception ex, DataPacket packet)

{(PacketDispatchException != null)

{(this, new PacketDispatchExceptionArgs(ex, packet));

}

}

/// <summary>

/// Occurs when the library generates a status update message

/// </summary>event InformationMessageHandler StatusUpdate;

/// <summary>

/// Raises the <see cref="StatusUpdate"/> event

/// </summary>

/// <param name="message">A status message</param>internal void OnStatusUpdate(string message)

{(StatusUpdate != null)(this, message);

}

/// <summary>

/// Occurs when the library generates a status update message during login

/// </summary>

public event LoginStatusUpdateHandler LoginStatusUpdate;

/// <summary>

/// Raises the <see cref="LoginStatusUpdate"/> event

/// </summary>

/// <param name="message">A status message</param>

/// <param name="percentdone">The percentage of the login progress that has been completed</param>internal void OnLoginStatusUpdate(string message, double percentdone)

{

if (LoginStatusUpdate != null)

{(this, message, percentdone);

}

}

/// <summary>

/// Occurs when the library generates a warning message

/// </summary>event WarningMessageHandler WarningMessage;

/// <summary>

/// Raises the <see cref="WarningMessage"/> event

/// </summary>

/// <param name="errorcode">A <see cref="ServerErrorCode"/> describing the warning</param>internal void OnWarning(ServerErrorCode errorcode)

{

// csammis: Losing a secondary connection (chat room, icon downloader)

// isn't cause for logging off the session...and setting LoggedIn to false

// doesn't log off the session anyway. Call .Logoff() for that.

//if (errorcode == ServerErrorCode.LostSecondaryConnection)

// this.LoggedIn = false;

(WarningMessage != null)

{(this, errorcode);

}

}

/// <summary>

/// Occurs when the library generates an error message

/// </summary>event ErrorMessageHandler ErrorMessage;

/// <summary>

/// Raises the <see cref="ErrorMessage"/> event or the <see cref="LoginFailed"/> event

/// </summary>

/// <param name="errorcode">A <see cref="ServerErrorCode"/> describing the error</param>

/// <remarks>If the login process has not completed, <see cref="LoginFailed"/> is raised.

/// Otherwise, <see cref="ErrorMessage"/> is raised.</remarks>internal void OnError(ServerErrorCode errorcode)

{(!_loggedin)

{(LoginFailed != null)

{(errorcode == ServerErrorCode.LostBOSConnection)

{= false;

LoginFailed(this, LoginErrorCode.CantReachBOSServer);

}(this, LoginErrorCode.UnknownError);

}

}

{(ErrorMessage != null)(this, errorcode);

}

}

#endregion

#region SNAC01 events

/// <summary>

/// Occurs when the login process is complete.

/// </summary>event LoginCompletedHandler LoginCompleted;

/// <summary>

/// Raises the <see cref="LoginCompleted"/> event

/// </summary>internal void OnLoginComplete()

{= true;(LoginCompleted != null)

{(this);

}

}

/// <summary>

/// Occurs when a remote client has warned this client

/// </summary>event WarningReceivedHandler WarningReceived;

/// <summary>

/// Raises the <see cref="WarningReceived"/> event.

/// </summary>

/// <param name="newlevel">The client's new warning level</param>

/// <param name="anonymous"><c>true</c> if this warning was sent anonymously, <c>false</c> otherwise</param>

/// <param name="ui">A <see cref="UserInfo"/> structure describing the warning user. If <paramref name="anonymous"/> is

/// <c>true</c>, this structure is unpopulated</param>internal void OnWarningReceived(ushort newlevel, bool anonymous, UserInfo ui)

{(WarningReceived != null)

WarningReceived(this, newlevel, anonymous, ui);

}

#endregion

#region SNAC02 events

/// <summary>

/// Occurs when the server sends acknowledgement of a directory update request

/// </summary>event DirectoryUpdateAcknowledgedHandler DirectoryUpdateAcknowledged;

/// <summary>

/// Raises the <see cref="DirectoryUpdateAcknowledged"/> event

/// </summary>

/// <param name="success"><c>true</c> if the directory update succeded, and <c>false</c> otherwise</param>internal void OnDirectoryUpdateAcknowledged(bool success)

{(DirectoryUpdateAcknowledged != null)(this, success);

}

#endregion

#region SNAC04 events

/// <summary>

/// Occurs when a file transfer request is received

/// </summary>event FileTransferRequestReceivedHandler FileTransferRequestReceived;

/// <summary>

/// Occurs when a Direct IM transfer request is received

/// </summary>event DirectIMRequestReceivedHandler DirectIMRequestReceived;

/// <summary>

/// Raises the <see cref="FileTransferRequestReceived"/> event

/// </summary>

/// <param name="key">The unique key needed to respond to this request</param>internal void OnDirectConnectionRequestReceived(Cookie key)

{conn = Connections.GetDirectConnectionByCookie(key);

(conn is FileTransferConnection && FileTransferRequestReceived != null)

{

var ftc = conn as FileTransferConnection;(this, ftc.Other, ftc.VerifiedIP, ftc.FileHeader.Name,.TotalFileSize, ftc.Message, key);

}if (conn is DirectIMConnection && DirectIMRequestReceived != null)

{

DirectIMRequestReceived(this, conn.Other, conn.Message, key);

}

//else if (rd.DirectConnection.ConnectionType == DirectConnectType.DirectIM &&

// this.OscarLib_DirectIMRequestReceived != null)

//{

// this.OscarLib_DirectIMRequestReceived(this, rd.UserInfo);

//}

}

/// <summary>

/// Occurs when a chat room invitation is received

/// </summary>

public event ChatInvitationReceivedHandler ChatInvitationReceived;

/// <summary>

/// Raises the <see cref="ChatInvitationReceived"/> event

/// </summary>

/// <param name="sender">A <see cref="UserInfo"/> object represnting the inviter</param>

/// <param name="roomname">The name of the chatroom</param>

/// <param name="message">An invitation chatroom</param>

/// <param name="encoding">The text encoding used in the chatroom</param>

/// <param name="language">The language used in the chatroom</param>

/// <param name="key">The unique key needed to respond to this request</param>internal void OnChatInvitationReceived(UserInfo sender,

string roomname,

string message,encoding,language,key)

{(ChatInvitationReceived != null)(this, sender, roomname, message, encoding, language, key);

}

#endregion

#region SNAC0F events

/// <summary>

/// Occurs when the server sends the results of a directory search

/// </summary>event SearchResultsHandler SearchResults;

/// <summary>

/// Raises the <see cref="SearchResults"/> event

/// </summary>

/// <param name="results">The results of the directory search</param>internal void OnSearchResults(DirectoryEntry[] results)

{(SearchResults != null)(this, results);

}

/// <summary>

/// Occurs when the server sends a list of interests

/// </summary>event InterestsReceivedHandler InterestsReceived;

/// <summary>

/// Raises the <see cref="InterestsReceived"/> event

/// </summary>

/// <param name="results">The results of the interests request</param>internal void OnInterestsReceived(InterestItem[] results)

{(InterestsReceived != null)(this, results);

}

#endregion

#region SNAC13 events

/// <summary>

/// Occurs when the buddy list has been completely sent by the server

/// </summary>event ContactListFinishedHandler ContactListFinished;

/// <summary>

/// Notifies the server to activate the SSI data for the client, and to begin

/// alerting its contacts that it is now online and ready to receive messages

///

/// Implementing clients should call <see cref="ActivateBuddyList"/> in response to this event

/// </summary>internal void OnContactListFinished(DateTime lastModificationDate)

{(ContactListFinished != null)

{= lastModificationDate;(this, lastModificationDate);

}

}

/// <summary>

/// Occurs when the server sends a new buddy item to the client

/// </summary>

public event BuddyItemReceivedHandler BuddyItemReceived;

/// <summary>

/// Raises the <see cref="BuddyItemReceived"/> event

/// </summary>

/// <param name="buddy">An <see cref="SSIBuddy"/> object</param>internal void OnBuddyItemReceived(SSIBuddy buddy)

{(BuddyItemReceived != null)(this, buddy);

}

/// <summary>

/// Occurs when a buddy item has been removed from the server-side list

/// </summary>event BuddyItemRemovedHandler BuddyItemRemoved;

/// <summary>

/// Raises the <see cref="BuddyItemRemoved"/> event

/// </summary>

/// <param name="buddy">An <see cref="SSIBuddy"/> object</param>internal void OnBuddyItemRemoved(SSIBuddy buddy)

{

if (BuddyItemRemoved != null)

{(this, buddy);

}

}

/// <summary>

/// Occurs when the server sends a new group item to the client

/// </summary>event GroupItemReceivedHandler GroupItemReceived;

/// <summary>

/// Raises the <see cref="GroupItemReceived"/> event

/// </summary>

/// <param name="group">An <see cref="SSIGroup"/>"/> object</param>internal void OnGroupItemReceived(SSIGroup group)

{

}

/// <summary>

/// Occurs when a buddy item has been removed from the server-side list

/// </summary>event GroupItemRemovedHandler GroupItemRemoved;

/// <summary>

/// Raises the <see cref="GroupItemRemoved"/> event

/// </summary>

/// <param name="group">An <see cref="SSIGroup"/> object</param>internal void OnGroupItemRemoved(SSIGroup group)

{(GroupItemRemoved != null)

{(this, group);

}

}

/// <summary>

/// Occurs when the server sends the master group item to the client

/// </summary>

public event MasterGroupItemReceivedHandler MasterGroupItemReceived;

/// <summary>

/// Raises the <see cref="MasterGroupItemReceived"/> event

/// </summary>

/// <param name="numgroups">The number of groups we are going to receive</param>internal void OnMasterGroupItemReceived(int numgroups)

{(MasterGroupItemReceived != null)(this, numgroups);

}

/// <summary>

/// Occurs when the an SSI edit is completed

/// </summary>event SSIEditCompleteHandler SSIEditComplete;

/// <summary>

/// Raises the <see cref="SSIEditComplete"/> event

/// </summary>

protected internal void OnSSIEditComplete()

{(SSIEditComplete != null)

{(this);

}

}

/// <summary>

/// Occurs when a client ask for authorization (ICQ)

/// </summary>event AuthorizationRequestReceivedHandler AuthorizationRequestReceived;

/// <summary>

/// Raises the <see cref="AuthorizationRequestReceived"/> event

/// </summary>

/// <param name="screenname">the screenname that ask for authorization</param>

/// <param name="reason">the reason message</param>internal void OnAuthorizationRequestReceived(string screenname, string reason)

{(AuthorizationRequestReceived != null)(this, screenname, reason);

}

/// <summary>

/// Occurs when a client granted or declined the authorization (ICQ)

/// </summary>event AuthorizationResponseReceivedHandler AuthorizationResponseReceived;

/// <summary>

/// Raises the <see cref="AuthorizationResponseReceived"/> event

/// </summary>

/// <param name="screenname">the screenname that should get the response</param>

/// <param name="authorizationGranted">Determines, if the authorization will be granted or not.</param>

/// <param name="reason">The reason message</param>internal void OnAuthorizationResponseReceived(string screenname, bool authorizationGranted,reason)

{(AuthorizationResponseReceived != null)(this, screenname, authorizationGranted, reason);

}

/// <summary>

/// Occurs when a client granted the authorization for the future (ICQ)

/// </summary>

public event FutureAuthorizationReceivedHandler FutureAuthorizationReceived;

/// <summary>

/// Raises the <see cref="FutureAuthorizationReceived"/> event

/// </summary>

/// <param name="screenname">the screenname that should get the future authorization</param>

/// <param name="reason">The reason message</param>internal void OnAuthorizationResponseReceived(string screenname, string reason)

{(FutureAuthorizationReceived != null)(this, screenname, reason);

}

#endregion

#region Authorization manager events

/// <summary>

/// Occurs when the login sequence fails

/// </summary>event LoginFailedHandler LoginFailed;

/// <summary>

/// Raises the <see cref="LoginFailed"/> event

/// </summary>

/// <param name="errorcode">A <see cref="LoginErrorCode"/> describing the failure</param>internal void OnLoginFailed(LoginErrorCode errorcode)

{(LoginFailed != null)

{

LoggedIn = false;(this, errorcode);

}

}

#endregion

#region Direct Connection events

/// <summary>

/// Occurs during a file transfer to indicate transfer progression

/// </summary>event FileTransferProgressHandler FileTransferProgress;

/// <summary>

/// Raises the <see cref="FileTransferProgress"/> event

/// </summary>

/// <param name="cookie">The rendezvous cookie belonging to the file being transfered</param>

/// <param name="bytestransfered">The number of bytes transfered so far</param>

/// <param name="bytestotal">The total number of bytes to be transfered</param>internal void OnFileTransferProgress(Cookie cookie,

uint bytestransfered, uint bytestotal)

{(FileTransferProgress != null)

{

FileTransferProgress(this, cookie, bytestransfered, bytestotal);

}

}

/// <summary>

/// Occurs during a DirectIM session to indicate the progress of an incoming message

/// </summary>

/// <remarks>This event will only fire if the incoming message contains attachments</remarks>

public event DirectIMIncomingMessageProgressHandler DirectIMIncomingMessageProgress;

/// <summary>

/// Occurs during a DirectIM session to indicate the progress of an outgoing message

/// </summary>

/// <remarks>This event will only fire if the outgoing message contains attachments</remarks>event DirectIMOutgoingMessageProgressHandler DirectIMOutgoingMessageProgress;

/// <summary>

/// Raises the DirectIM message progress events

/// </summary>

/// <param name="incoming">A value indicating whether the message is incoming or outgoing</param>

/// <param name="cookie">The rendezvous cookie belonging to the DirectIM session</param>

/// <param name="bytestransfered">The number of bytes transfered so far</param>

/// <param name="bytestotal">The total number of bytes to be transfered</param>internal void OnDirectIMMessageProgress(bool incoming, Cookie cookie, uint bytestransfered,

uint bytestotal)

{(incoming)

{(DirectIMIncomingMessageProgress != null)

{

DirectIMIncomingMessageProgress(this, cookie, bytestransfered, bytestotal);

}

}

{(DirectIMOutgoingMessageProgress != null)

{(this, cookie, bytestransfered, bytestotal);

}

}

}

/// <summary>

/// Occurs when a file transfer has been cancelled

/// </summary>event FileTransferCancelledHandler FileTransferCancelled;

/// <summary>

/// Raises the <see cref="FileTransferCancelled"/> event

/// </summary>

/// <param name="other">The <see cref="UserInfo"/> of the user on the other side of the connection</param>

/// <param name="cookie">The rendezvous cookie belonging to the cancelled file</param>

/// <param name="reason">The reason for the cancellation</param>internal void OnFileTransferCancelled(UserInfo other, Cookie cookie, string reason)

{(FileTransferCancelled != null)

{(this, other, cookie, reason);

}

}

/// <summary>

/// Raised when a DirectIM session has been cancelled

/// </summary>event FileTransferCancelledHandler DirectIMSessionCancelled;

/// <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>internal void OnDirectIMSessionCancelled(DirectConnection conn, string reason)

{.RemoveDirectConnection(conn.Cookie);

Messages.SendDirectConnectionCancellation(conn, reason);

(DirectIMSessionCancelled != null)

{(this, conn.Other, conn.Cookie, reason);

}

}

/// <summary>

/// Raised when a DirectIM session has been closed

/// </summary>event DirectIMSessionChangedHandler DirectIMSessionClosed;

/// <summary>

/// Raises the <see cref="DirectIMSessionClosed"/>

/// </summary>

/// <param name="other">A <see cref="UserInfo"/> object describing the other session participant</param>

/// <param name="cookie">The rendezvous cookie belonging to the cancelled session</param>internal void OnDirectIMSessionClosed(UserInfo other, Cookie cookie)

{.RemoveDirectConnection(cookie);

if (DirectIMSessionClosed != null)

{(this, other, cookie);

}

}

/// <summary>

/// Raised when a DirectIM session is ready for data

/// </summary>event DirectIMSessionChangedHandler DirectIMSessionReady;

/// <summary>

/// Raises the <see cref="DirectIMSessionReady"/> event

/// </summary>

/// <param name="other">A <see cref="UserInfo"/> object describing the other session participant</param>

/// <param name="cookie">The rendezvous cookie belonging to the session</param>internal void OnDirectConnectionComplete(UserInfo other, Cookie cookie)

{(DirectIMSessionReady != null)

{(this, other, cookie);

}

}

/// <summary>

/// Occurs when a file transfer has completed

/// </summary>event FileTransferCompletedHandler FileTransferCompleted;

/// <summary>

/// Raises the <see cref="FileTransferCompleted"/> event

/// </summary>

/// <param name="cookie">The rendezvous cookie belonging to the completed file</param>internal void OnFileTransferCompleted(Cookie cookie)

{(FileTransferCompleted != null)

{(this, cookie);

}

}

/// <summary>

/// Occurs when a Direct IM has been received

/// </summary>event DirectIMReceivedHandler DirectIMReceived;

/// <summary>

/// Raises the <see cref="OscarLib_DirectIMReceived"/> event

/// </summary>

/// <param name="message">The <see cref="DirectIM"/> received</param>internal void OnDirectIMReceived(DirectIM message)

{(DirectIMReceived != null)

{(this, message);

}

}

#endregion

#endregion

}

}

Похожие работы на - ICQ-клиент

 

Не нашли материал для своей работы?
Поможем написать уникальную работу
Без плагиата!