📄 iksdemo.cpp
字号:
/* ** Copyright (C) 2005 Darrell Karbott (djk2005@users.sf.net)** This code is free software; you can redistribute it and/or modify** it under the terms of the GNU Public Licence (GPL) version 2 See** http://www.gnu.org/ for further details of the GPL.*/#include "iksdemo.h"#include <string.h>#include <stdio.h>#include <stdlib.h>// Helper macros to check return values from iksemel functions.#define IKS_CHK(iksErrCode) { checkIksReturnValue(iksErrCode, __FILE__, __LINE__); }#define IKS_CHK_PTR(ptr) { checkIksReturnValue((ptr ? IKS_OK : IKS_NOMEM), __FILE__, __LINE__); }// MUST be static or the symbian linker complains.static const char DEFAULT_JABBER_RESOURCE[] = "iksdemo";IUserInterface::~IUserInterface() {}IUserInteractions::~IUserInteractions() {}////////////////////////////////////////////////////////////class CInteractions : public IUserInteractions {public: CInteractions(CIksDemo* parent) : mParent(parent) {} virtual ~CInteractions() {} virtual int connect(const char* jid, const char* password, int port) { return mParent->connect(jid, password, port); } virtual void disconnect() { // Send the end of stream tag and wait for the server // to drop the connection. mParent->disconnect(0); } virtual int sendMsg(const char* toJid, const char* msg) { return mParent->send(toJid, msg); }private: CIksDemo* mParent;};////////////////////////////////////////////////////////////// Malloc wrappers used to test iks_set_mem_funcs()#ifdef USE_IKS_MALLOC_HOOKS// SYMBIAN// The log file ends up in the emulator root directory.// e.g. for UIQ_21:// C:\Symbian\UIQ_21\epoc32\winscw\c\logged_malloc.log// or in the phone's root directory when running on a// real device.void *logged_malloc(size_t size){ void* ret = malloc(size); FILE* fOut = fopen("logged_malloc.log", "a+"); if (fOut) { fprintf(fOut, "%p mallocd [%x]\n", ret, size); fflush(fOut); fclose(fOut); } return ret;}void logged_free(void *ptr){ FILE* fOut = fopen("logged_malloc.log", "a+"); if (fOut) { fprintf(fOut, "%p free\n", ptr); fflush(fOut); fclose(fOut); } free(ptr);}#endif////////////////////////////////////////////////////////////CIksDemo::CIksDemo(ikstransport* transport) : mTransport(transport), mUi(NULL), mInteractions(NULL), mPrs(NULL), mState(QUIESCENT), mWriteCount(0), mWrittenCount(0), mReadCount(0), mIsDisconnecting(0){ mJid[0] = 0; mPassword[0] = 0;#ifdef USE_IKS_MALLOC_HOOKS iks_set_mem_funcs(logged_malloc, logged_free);#endif}CIksDemo::~CIksDemo(){ disconnect(); delete mInteractions;#ifdef USE_IKS_MALLOC_HOOKS // You must do this or the TLS memory will leak. iks_set_mem_funcs(NULL, NULL);#endif}int CIksDemo::init(IUserInterface* ui){ mInteractions = new CInteractions(this); if (!mInteractions) { return 0; } mUi = ui; if (!mTransport) { mUi->displayErrorMsg("ASSERTION: mTransport"); return 0; } if (!mTransport->connect_async) { mUi->displayErrorMsg("ASSERTION: mTransport->connect_async"); return 0; } return 1;}void CIksDemo::releaseUi() { mUi = NULL; }IUserInteractions* CIksDemo::cmd(){ return mInteractions;}int CIksDemo::StreamHook(void *user_data, int type, iks *node){ return ((CIksDemo*)user_data)->streamHook(type, node);}void CIksDemo::LogHook(void *user_data, const char *data, size_t size, int is_incoming){ ((CIksDemo*)user_data)->logHook(data, size, is_incoming);}int CIksDemo::SocketHook(void *user_data, iksasyncevent* event){ return ((CIksDemo*)user_data)->socketHook(event->event, event->data0, event->data1);}int CIksDemo::streamHook(int type, iks *node){#ifdef ENABLE_DEBUG_PRINTFS printf("CIksDemo::streamHook: %i\n", type);#endif if (mIsDisconnecting) { iks_delete(node); // Tell parser to stop parsing. return IKS_HOOK; } switch (type) { case IKS_NODE_START: { // First send authorization iksid* id = iks_id_new(iks_stack(node), mJid); IKS_CHK_PTR(id); id->resource = (char*)DEFAULT_JABBER_RESOURCE; // REDFLAG: resource really is const right? investigate. ikspak* pak = iks_packet(node); IKS_CHK_PTR(pak); char* sid = iks_find_attrib(pak->x, "id"); IKS_CHK_PTR(sid); iks* msg = iks_make_auth (id, mPassword, sid); IKS_CHK_PTR(msg); IKS_CHK_PTR(iks_insert_attrib(msg, "id", "auth")); IKS_CHK(iks_send(mPrs, msg)); iks_delete(msg); } break; case IKS_NODE_NORMAL: { ikspak* pak = iks_packet(node); IKS_CHK_PTR(pak); char* id = iks_find_attrib(pak->x, "id"); //IKS_CHK_PTR(id); not an error if (id) { if (0 == strcmp("auth", id)) { if (pak->subtype == IKS_TYPE_RESULT) { state(AUTHORIZED); // Set presence to available. iks* pres = iks_make_pres (IKS_SHOW_AVAILABLE, NULL); IKS_CHK_PTR(pres); IKS_CHK(iks_send(mPrs, pres)); iks_delete(pres); } else if (pak->subtype == IKS_TYPE_ERROR) { displayErrorPacket(pak); state(ERROR); iks_delete(node); disconnect(); return IKS_HOOK; } else { iks_delete(node); return IKS_HOOK; } } } packet(pak); } break; // hmmmm.... case IKS_NODE_STOP: case IKS_NODE_ERROR: iks_delete(node); // This will eventually cause iks_parse to return // an error code. return IKS_HOOK; } iks_delete(node); return IKS_OK;}#ifndef ENABLE_DEBUG_PRINTFSvoid CIksDemo::logHook(const char* , size_t, int ) {}#elsevoid CIksDemo::logHook(const char * data, size_t /*size*/, int is_incoming){ if (is_incoming) { printf("RECV:%s\n", data); } else { printf("SENT:%s\n", data); }}#endif int CIksDemo::socketHook(int reason, int data0, int data1){#ifdef ENABLE_DEBUG_PRINTFS printf("CIksDemo::socketHook: %i %i %i\n", reason, data0, data1);#endif switch (reason) { case IKS_ASYNC_RESOLVED: state(RESOLVED); break; case IKS_ASYNC_CONNECTED: state(CONNECTED); break; case IKS_ASYNC_WRITE: mWriteCount += data0; break; case IKS_ASYNC_WRITTEN: mWrittenCount += data0; break; case IKS_ASYNC_READ: if (mPrs) { int ret = iks_recv(mPrs, 0); // Ignore the IKS_HOOK we caused in the streamHook. if (ret != IKS_HOOK) { IKS_CHK(ret); if (IKS_OK != ret) { disconnect(); break; } } mReadCount += data0; } break; case IKS_ASYNC_CLOSED: if (mPrs && mUi) { // You shouldn't be able to get here except // as the result of iks_disconnect(); mUi->displayErrorMsg("ASSERTION: !mPrs"); } state(QUIESCENT); break; case IKS_ASYNC_ERROR: // We expect the server to drop the connection // when the </stream:stream> tag is sent. if (data0 == IKS_NET_DROPPED && mIsDisconnecting) { disconnect(); return IKS_OK; } // The error was not expected. displaySocketError(data0, data1); state(ERROR); disconnect(); break; } return IKS_OK;}void CIksDemo::state(const LoginStates& state){ if (mState == state) { return; } mState = state; const char* statusMsg = "???"; switch (mState) { case QUIESCENT : statusMsg="QUIESCENT"; break; case CONNECTING: statusMsg="CONNECTING"; break; case RESOLVING: statusMsg="RESOLVING"; break; case RESOLVED: statusMsg="RESOLVED"; break; case CONNECTED: statusMsg="CONNECTED"; break; case AUTHORIZED: statusMsg="AUTHORIZED"; break; case ERROR: statusMsg="ERROR"; break; } if (mUi) { mUi->displayStatusMsg(statusMsg); }}int CIksDemo::connect(const char* jid, const char* password, int port){ if (strlen(jid) >= MAX_JID_LEN || strlen(password) >= MAX_PASSWORD_LEN) { return 0; } disconnect(); // Parse user id and server name out of the jid ikstack* s = iks_stack_new(256, 0); IKS_CHK_PTR(s); if (!s) { return 0; } iksid* id = iks_id_new (s, jid); IKS_CHK_PTR(id); if (!id) { iks_stack_delete(s); return 0; } if ((!(id->user)) || (!(id->server))) { iks_stack_delete(s); return 0; } mPrs = NULL; strcpy(mJid, jid); strcpy(mPassword, password); mWriteCount = 0; mWrittenCount = 0; mReadCount = 0; mIsDisconnecting = 0; // Create parser instance mPrs = iks_stream_new (IKS_NS_CLIENT, this, CIksDemo::StreamHook); IKS_CHK_PTR(mPrs);#ifdef ENABLE_DEBUG_PRINTFS // Optional logging of data coming into and out of socket. iks_set_log_hook (mPrs, CIksDemo::LogHook);#endif // Connect. int ret = iks_connect_async_with (mPrs, id->server, port, id->server, mTransport, this, CIksDemo::SocketHook); IKS_CHK(ret); iks_stack_delete(s); return ret == IKS_OK;}void CIksDemo::disconnect(int bHard){ if (!mPrs) { return; } // Force a hard disconnect when called while waiting for // a soft disconnect to complete. if (bHard || mIsDisconnecting) { iksparser* deadManWalking = mPrs; mPrs = NULL; iks_disconnect(deadManWalking); iks_parser_delete(deadManWalking); } else { // Tell the server we have gone away. iks* pres = iks_make_pres (IKS_SHOW_UNAVAILABLE, NULL); IKS_CHK_PTR(pres); IKS_CHK(iks_send(mPrs, pres)); iks_delete(pres); // Send the end of stream tag. IKS_CHK(iks_send_raw(mPrs, "</stream:stream>")); // Wait for the server to drop the socket connection. mIsDisconnecting = 1; }}void CIksDemo::packet(ikspak* packet){ // For now, all all we do is display the // body of message packets. // if (packet->type == IKS_PAK_MESSAGE) { const char* from = ""; const char* msg = ""; if (packet->from->full) { from = packet->from->full; } iks* body = iks_find(packet->x, "body"); if (body) { if (iks_cdata(iks_child(body))) { msg = iks_cdata(iks_child(body)); } } if (mUi) { mUi->displayJabberMsgFrom(from, msg ); } }}// Send a Jabber message.int CIksDemo::send(const char* toJid, const char* msg){ if (mState != AUTHORIZED) { return 0; } iks* node = iks_new("message"); IKS_CHK_PTR(node); IKS_CHK_PTR(iks_insert_attrib(node, "to", toJid)); iks* body = iks_insert(node, "body"); IKS_CHK_PTR(body); IKS_CHK_PTR(iks_insert_cdata(body, msg, 0)); int ret = iks_send(mPrs, node); IKS_CHK(ret); iks_delete(node); return ret == IKS_OK;}void CIksDemo::checkIksReturnValue(int err, const char* file, int line){ if (err == IKS_OK || (!mUi)) { return; } char buff[512]; sprintf(buff, "iks function failed: %s:%i ret: %i", file, line, err);#ifdef ENABLE_DEBUG_PRINTFS printf("RUNTIME ERROR: %s\n", buff);#endif mUi->displayErrorMsg(buff);}void CIksDemo::displayErrorPacket(ikspak* pak){ if (!mUi) { return; } const char* code = ""; const char* msg = ""; iks* node = iks_find(pak->x, "error"); if (node) { code = iks_find_attrib(node, "code"); msg = iks_cdata(iks_child(node)); } char buff[512]; sprintf(buff, "%s %s", code, msg);#ifdef ENABLE_DEBUG_PRINTFS printf("ERROR PACKET: %s\n", buff);#endif mUi->displayErrorMsg(buff);}void CIksDemo::displaySocketError(int data0, int data1){ if (!mUi) { return; } char buff[512]; sprintf(buff, "IKS_ASYNC_ERROR: %i %i", data0, data1);#ifdef ENABLE_DEBUG_PRINTFS printf("%s\n", buff);#endif mUi->displayErrorMsg(buff);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -