Pichat developer documentation

Last update 25/May/2011 by Mark Seuffert

1. Introduction

Learn how to write own chat features and awake the chat with more life. This document is for developers who want to extend their chat and gives you an introduction of how to communicate with chat servers and write own plugins. There is also a software development kit (Pichat SDK) for download which comes with libraries, examples and unit tests.

2.1. Simple chat clients

Pichat supports a text chat protocol which makes it very easy to access chatrooms on a chat server. The idea is to enable the implementation of small, simple chat clients and also to simplify the communication between multiple chat applications.
What you need to do in your client: Connect to a chat server and send the login sequence below as first line, all arguments are optionally. A chat server identifies itself by sending "PICHAT" (hex 0x50 0x49 0x43 0x48 0x41 0x54) as first six bytes of identification, otherwise terminate connection immediately. If you are successfully connected show received text lines to the user and send typed in text lines to the server. The chat server does the rest and provides you with a complete text description of what's happening in the chat. No parsing required, easy peasy lemon squeezy.
Optionally, clients can suppport ping replies and lag detection. For this you need to enable the PINGSUPPORT setting when connecting, e.g. by sending the command /ECHO SETSILENT PINGSUPPORT. The chat server will then send additional text lines beginning with "!PING" or "!SERVER_PING", which the client has to answer immediately with a /PINGREPLY and the received text. The client can also send in regular intervalls a /PINGREPLY KEEPALIVE (e.g. after 150 seconds without server ping).
Syntax:PICHAT/TEXTCHAT nickname, chatroom, language, authentication, useragent, format, localtime, timehours
nickname=nickname of user (none for interactive login mode),
alternative nicknames can be separated by colon
chatroom=name of chatroom (none for default chatroom)
language=preferred language, ISO639 (none for English),
multiple languages can be separated by colon
authentication=optional user name and password of registered user,
values are separated by colon and then base64 encoded
useragent=name of user agent (none for unnamed text chat)
format=text format, one of the following:
RAW = raw text (default)
TEXT = plaintext without colors and bold
ANSI = text with colors and bold
XML = text with meta information
localtime=current time as hh:mm:ss (default is 00:00:00)
timehours=hours format, 12 or 24 (default is 24)
PICHAT/TEXTCHAT Moak, Flirt, de,, talker, TEXT, 14:30:05, 24
First example connects to a chat server using the nickname 'Moak'. The second example connects a text client with German language to the chatroom 'Flirt' and also sets a local time. The third example connects as registered user with the user name 'aladdin' and password 'opensesame'.
Notes: The protocol is line based plaintext (8-bit-characters), each line is separated through \r\n (CRLF). Default listening port of a chat server is 9009 TCP. Under no circumstances must the login sequence be extended with more arguments. which would lead to incompatibility. Application specific extensions shall go into separate lines, for example echo settings.

2.2. Simple chat status query

Pichat offers a simple chat status query, you can check if a chat server is online and see how many users are there. Connect to a chat server and send the status sequence below. A chat server identifies itself by sending "PICHAT" as first six bytes of identification, then returns version information, server status (users, activity, dedicated, chat mode, lag), extended server status (users-served, traffic, uptime, interests) and another line with server name, entrance and welcome message. After that the client will be disconnected.
Syntax:PICHAT/STATUS user-identification, name, language, useragent
user-identification=identification of user
name=name of user or chat server
language=preferred language, ISO639 (none for English),
multiple languages can be separated by colon
useragent=name of user agent (none for unnamed client)
Examples:PICHAT/STATUS moak@unknown, Moak
PICHAT/STATUS moak@unknown, Moak, sv, mybot/1.0 (+http://myserver)
First example queries chat status as user 'Moak', the second example requests chat status in Swedish language and includes an detailed user agent description.
Here's a typical chat server response:
!SERVER_VERSION Pichat Server v0.4.2 b60
!SERVER_STATUS 4,38,0,1,0
!SERVER_STATUS_EXTENDED 64,64738,6510,chat,music,pizza
!SERVER_INFO Moak's Chat,Entrance,Welcome to Moak's chat
!CONNECT_STATUS 203 Done, end of connection
Notes: Clients should not request the chat status more than once per minute to avoid flooding a chat server. Alternatively, the chat status is also available as web page and RSS feed (XML format). For further information please see status and statistics.

3. Plugin programming

Pichat supports plugins to add additional features to chat and web server. Plugins can be used for a variety of things, from handling chat actions such as users joining a chatroom up to chat bots that interact independently with users in the chat. Plugin are typically written in the C++ programming language.
What you need to do in your own plugin: Basically are all plugins shared libraries that implement a C++ interface and export a function called CreatePlugin().
Here's an example source code:
using namespace PichatCore; namespace Plugin { class CImplementation : public IPluginInterface { public: CImplementation(IApplicationInterface* pApi) { //TODO: more code here } virtual ~CImplementation() { } virtual void DeleteThis() const { delete this; } virtual const char* GetVersionName() const { return "Example.Simple"; } virtual const char* GetVersionDescription() const { return "Chat plugin example"; } virtual int GetVersionNumber() const { return 0x000101; } //note: v0.1.1 virtual const char* GetAuthor() const { return "Created by Moaky Moak"; } }; }; PLUGINEXAMPLE_EXPORT IPluginInterface* CreatePlugin(IApplicationInterface* pApi) { return new Plugin::CImplementation(pApi); }
When a plugin is created it usually receives a pointer to an application interface which gives access to chat functionality ('pApi' in code above).
Here another example source code, with some extensions to the previous example:
using namespace PichatCore; namespace Plugin { class CImplementation : public IPluginInterface, public ICoreServerInterface { public: CImplementation(IApplicationInterface* pApi) { m_pApi = pApi; if(m_pApi) m_pApi->SetCoreServerHandler(this, this); } virtual ~CImplementation() { } virtual void DeleteThis() const { delete this; } virtual const char* GetVersionName() const { return "Example.Simple"; } virtual const char* GetVersionDescription() const { return "Chat plugin example"; } virtual int GetVersionNumber() const { return 0x000102; } //note: v0.1.2 virtual const char* GetAuthor() const { return "Created by Moaky Moak"; } protected: virtual void OnChatServer(int nChatAction, ChatActions::ChatCallbackData data) { ASSERT(m_pApi); if(nChatAction == ChatActions::CHAT_SERVER_ONLINE) m_pApi->ProcessChatCommand("/STATUSTEXT Hello world"); } virtual void OnHttpServer(int nRequestType, ChatActions::HttpCallbackData data) {} private: IApplicationInterface* m_pApi; //application interface }; }; PLUGINEXAMPLE_EXPORT IPluginInterface* CreatePlugin(IApplicationInterface* pApi) { return new Plugin::CImplementation(pApi); }
The plugin uses an interface to request chat events from the server ('ICoreServerInterface' in code above) and outputs 'Hello world' when the server goes online. It's good to have a look at existing plugins and investigate how they work. There are examples showing you how to read preferences or how to create own chat bots, there are also two libraries PichatCore and SharkEngine to assist you in writing plugins. For further information please see Pichat SDK.
Notes: All plugins are loaded on application startup. You can see present plugins with the /PLUGIN command in the chat. The plugin version name has the format 'category.type', where category describes the offered service such as 'bot' or 'webcam'.

4. Join the development team

You enjoy creating software with graphics and networking. Why not working together and improve this project together? Pichat is technically based on C++, STL and a platform independent core that runs on Linux, BSD and Windows. Doesn't that sound like fun programming to you... :)
  • Plugin development: Write chat plugins for all kind of nice stuff, improve chat and webchat with new features. Download the Pichat SDK and start coding your own chat features. Basic programming skills in C++ required.
  • Client development: Write native code for a specific platform or programming language. Create a new chat client in your favourite programming language, how about a chat for a mobile phone? Basic programming skills required.
  • PichatCore development: Write platform independent code and design new chat features. Pichat is constantly envolving and new features will be added. Good knowledge of peer-to-peer networks (P2P) and chat systems required.
See what's planned next on the road map.

Appendix A: Pichat class diagram example

The following diagram shows an example design for a peer-to-peer chat application. Usually an application is client and server at once, plus a graphical user interface on top. Basically the same design is also used in existing Pichat software. Lines show HasA relationships between classes and not inheritance. An asterisk emphasises a many-to-one relationship.
CPichat | . . . . . . | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . | DATA CPichat ________ CPichat _______________________________________________________________________________________________ PART MainFrame MainData | | | | | | | CPichatClientManager CPichatServerManager CPichatPluginManager | | | | | | | | | | |___ CPichatMain |___ CSocketClientPreferences |___ CSocketServerPreferences |___ CPichatPluginPreferences | | | | Preferences | | | | | | | |___*CClientConnection |___ CSocketServerPichat |___*CPichatPlugin | | | |___ CPichatGui |___ CSocketClientPichat |___ CSocketServerHttp | | | | Preferences |___ CSocketHelperDns |___ CSocketObserverPichat | | | | | | | |___ CPichatContacts | | | Preferences | | | . . . . . | | | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . | | | GUI | | |_____ CSystemTray PART | | | |_______ CPichatDialogManager ___________________________________________________ | | | | CPichat CPichat *CPichat |___ CPichat Dialog3D DialogMain DialogChat | DialogAbout | | | |___*CPichatViewConnection |___ CPichatViewConnection |___ CPichat | |___ CTextBoxChat |___ CTextBoxChat | DialogStatus | |___ CListBoxSide |___ CListBoxSide | | |___ CEditBoxChat |___ CEditBoxChat |___ CPichat | DialogOptions |___ CPichatViewStatus |___ CPichatViewContacts |___ CPichatViewButtons
Figure 1: Example class design
While the 'DATA PART' typically is implemented platform independent and shared between different platforms, the 'GUI PART' is implemented platform specific to match best to the native user interface and therefore offers a native look and feel. A special case is the class CPichat that kicks off the application framework, it is different for each purpose.
Pichat is created with the idea of agile software development in mind: First make it work, then make it better. So it's no big surprise that one of the biggest design goal for Pichat is maintainability (design to fit the needs, but at the same time love and expect changes). There are two main software design factors I am personally looking at: First, which functionality does a class offer, is its (public) interface intuitive and safe to use? Secondly, how does the information flow work, is it elegant and efficient?

Appendix B: Pichat information flow example

This diagram shows information flow of text input with an example. Typically text input comes from a view, a client sends it then to a server, data is being processed there, again received by the client and finally text output is shown in a chat window. Both client side and server side are able to process chat commands.
CClientConnectionView CClientConnection ::SendInput() ---------> ::SendInput() ----------------------- | | \ / \ / CClientConnection CSocketClient ::ProcessChatCommand() --> ::SendInput() | ------------------------| | | | \ / | CSocketClient CSocketNode | ::Send() ------------ TCP --> ::OnReceiveLine() | | | \ / | CSocketNode CSocketServer | ::ProcessChatCommand() --> ::SendAll() | | | | \ / | | CSocketClient CSocketNode | |--------------- ::OnReceiveLine() <-- TCP --- ::Send() <----------------------- | | | | | | | \ / | CSocketClient \ / ::ProcessChatAction() CClientConnectionView CClientConnection | ::OnChatText() <----------- ::OnChatClientCallback() <------- | \ / CClientConnectionStatusView CClientConnectionManager ::OnChatNetwork() <-------- ::SendAllStatus()
Figure 2: Example information flow of text input

Appendix C: Pichat development philosophy

The development philosophy behind Pichat.
  • Improve technology. Are open minded for new ways, learn and are curious!
  • Share information. Collaboration and good processes make life easier!
  • Have fun in life. Keep motivation high all the time!
Let me explain what I mean with good processes. I think that processes are more important than the organisation or the structure of a system (e.g. processes are in my experience more relevant than the hierarchy of a development group). A structure is always something static that tries to organise the information flow and the purpose of individuals inside. But what we actually want to achieve is creating an efficient system that delivers maximised output (software in our case) and adapts itself to changing circumstances.
Let's see it from this perspective and accordingly optimise information flow and its key components: Such as information distribution, communication between individuals, organisation of team work and safe guards to minimise risks or problems that show up on the way. Structures are better built on processes than the other way around (e.g. when you wrongly build processes on existing structures you have already made design decisions that weaken structural self organisation, possibly limit information flow and efficiency of team work). In a similar way are individuals better defined by their tasks and strengths rather than by a position (e.g. there is generally the sneaking danger of hierarchical structures defining themself by their position and less by the real purpose they fullfill or the processes that would otherwise be applied, people in key positions are tempted to put personal interests over goals of the whole system).
Organisation of team work is best when different planing parties (e.g. technical and non technical planing) work equally together and define their tasks as a looking ahead assistance for others. For example take commercial software projects which often suffer from "management" trying to control instead of aiding the creative design processes. As a result are problems and product shortcomings often denied until it is too late. A proper management would requires that different planing parties work together, including engineers and customers. There is also a deeply rooted misunderstanding of what "software engineering" is, I believe it's a design discipline and not a deterministic engineering discipline at all (software engineers spend more time on software design decisions than on building software, eminent requirements will emerge during the whole development life cycle). However, a bigger problem than technical hurdles are usually individuals and the lack of communication between them. For example let five people work together, watch how misunderstandings and dislikes grow and opinions collide in a non productive way. Let's face it, we all have to deal with incompetence and insensitivity, hopefully not every day, but we need to develop strategies to deal with it and also how to integrate problematic persons into our day to day work. Some tips: allow people to create a personal relationship to you, explore problems and feelings in a personal dialogue (not in front of others). A few more psychological aspects to look at: a lack of clearness and security cause humans to feel unhappy, a lack of vision and purpose causes humans to disconnect from a project. But on the other hand (a manageable level of) responsibility and challenge are directly related to higher productivity and joy.
Ideally, there should be processes in place to monitor and improve the overall effectiveness and health status of a system (or 'Wohlfühlstatus' in German, a word that describes the feeling-good-state of a complete system and its individuals, it's an empathic expression that underlines the importance of the human side). For example take a development group that produces output but is unhappy, it will sooner or later collapse or needs time to raise to a next level. On the other hand take a motivated but inefficient development group, it will produce no satisfying output and needs time to raise productivity and quality. There is generally nothing you can do against bad politics and wrong people in powerful positions other than to de-power those people quickly (remember to focus on building processes not structures).
Summing it up, I believe that software processes are utterly important for any software project, to create an environment where ideas are allowed to be realised and people enjoy working with each other.
Pichat is a simple to use chat software. It comes with integrated LAN messenger and webchat. The chat server supports multiple chatrooms, text formatting with smileys and a user-friendly webchat (HTML, CSS, DOM, JavaScript). The webchat works with nearly any web browser, easily integrated into your design, no PHP/Flash/Java required. Software for free information exchange for Linux and Windows. Built with Yellow