From 2bf023f2ffaf9b366662c21fdb36c2ff19a5b747 Mon Sep 17 00:00:00 2001 From: "sbbird.zhu" Date: Sun, 24 Nov 2013 15:36:31 +0900 Subject: [PATCH] first commit --- FlashAPI/XMLSocketd/Connection.as | 108 +++++ FlashAPI/XMLSocketd/Room.as | 161 +++++++ FlashAPI/XMLSocketd/User.as | 34 ++ FlashAPI/example.fla | Bin 0 -> 39936 bytes FlashAPI/example.html | 21 + FlashAPI/example.swf | Bin 0 -> 7768 bytes FlashAPI/example_simple.as | 142 +++++++ FlashAPI/join/index.php | 16 + FlashAPI/whiteboard.as | 64 +++ FlashAPI/whiteboard.fla | Bin 0 -> 40960 bytes Makefile | 24 ++ Makefile.win | 59 +++ README.md | 0 gmon.out | Bin 0 -> 171632 bytes pthreadGC.dll | Bin 0 -> 62847 bytes server.dev | 259 ++++++++++++ server.ico | Bin 0 -> 6830 bytes server.layout | 154 +++++++ src/Game.cpp | 135 ++++++ src/Game.h | 94 +++++ src/authorizehttpconnection.cpp | 97 +++++ src/authorizehttpconnection.h | 40 ++ src/config.h | 22 + src/httpconnection.cpp | 143 +++++++ src/httpconnection.h | 66 +++ src/main.cpp | 191 +++++++++ src/message.cpp | 25 ++ src/message.h | 26 ++ src/player.cpp | 73 ++++ src/player.h | 57 +++ src/room.cpp | 103 +++++ src/room.h | 34 ++ src/roommember.cpp | 121 ++++++ src/roommember.h | 42 ++ src/server.cpp | 668 ++++++++++++++++++++++++++++++ src/server.h | 75 ++++ src/server_private.h | 23 + src/stringqueue.cpp | 55 +++ src/stringqueue.h | 32 ++ src/user.cpp | 380 +++++++++++++++++ src/user.h | 64 +++ src/xmlparser.cpp | 226 ++++++++++ src/xmlparser.h | 41 ++ xmlsocketd.prj | 236 +++++++++++ xmltags.txt | 17 + 45 files changed, 4128 insertions(+) create mode 100755 FlashAPI/XMLSocketd/Connection.as create mode 100755 FlashAPI/XMLSocketd/Room.as create mode 100755 FlashAPI/XMLSocketd/User.as create mode 100755 FlashAPI/example.fla create mode 100755 FlashAPI/example.html create mode 100755 FlashAPI/example.swf create mode 100755 FlashAPI/example_simple.as create mode 100755 FlashAPI/join/index.php create mode 100755 FlashAPI/whiteboard.as create mode 100755 FlashAPI/whiteboard.fla create mode 100755 Makefile create mode 100755 Makefile.win create mode 100644 README.md create mode 100755 gmon.out create mode 100755 pthreadGC.dll create mode 100755 server.dev create mode 100755 server.ico create mode 100755 server.layout create mode 100644 src/Game.cpp create mode 100644 src/Game.h create mode 100755 src/authorizehttpconnection.cpp create mode 100755 src/authorizehttpconnection.h create mode 100755 src/config.h create mode 100755 src/httpconnection.cpp create mode 100755 src/httpconnection.h create mode 100755 src/main.cpp create mode 100755 src/message.cpp create mode 100755 src/message.h create mode 100644 src/player.cpp create mode 100644 src/player.h create mode 100755 src/room.cpp create mode 100755 src/room.h create mode 100755 src/roommember.cpp create mode 100755 src/roommember.h create mode 100755 src/server.cpp create mode 100755 src/server.h create mode 100755 src/server_private.h create mode 100755 src/stringqueue.cpp create mode 100755 src/stringqueue.h create mode 100755 src/user.cpp create mode 100755 src/user.h create mode 100755 src/xmlparser.cpp create mode 100755 src/xmlparser.h create mode 100755 xmlsocketd.prj create mode 100755 xmltags.txt diff --git a/FlashAPI/XMLSocketd/Connection.as b/FlashAPI/XMLSocketd/Connection.as new file mode 100755 index 0000000..2465bc4 --- /dev/null +++ b/FlashAPI/XMLSocketd/Connection.as @@ -0,0 +1,108 @@ +class XMLSocketd.Connection{ + + private var oSocket:XMLSocket; + private var bConnected:Boolean = false; + private var aRooms:Array; + + var sState:String = "disconnected"; + + var iPort:Number; + var sURL:String; + + // Events + var onConnect = false; + var onDisconnect = false; + var onError = false; + + + function Connection(){ + + this.aRooms = new Array(); + XMLSocket.prototype.oObject = this; + this.oSocket = new XMLSocket(); + this.iPort = 2584; + + // Base directory for SWF-file + this.sURL = _root._url; + var iLastSlash = this.sURL.lastIndexOf("/"); + if(iLastSlash!=-1){ + this.sURL = this.sURL.substring(0,iLastSlash); + } + + + } + + + + function connect(){ + this.sState = "connecting"; + this.oSocket.onConnect = function (bSuccess){ + this.oObject.socketOnConnect(bSuccess); + } + this.oSocket.onXML = function (oXML){ + this.oObject.socketOnXML(oXML); + } + + if(_root._url.indexOf("http:")==-1){ + this.oSocket.connect("127.0.0.1",this.iPort); + }else{ + this.oSocket.connect(null,this.iPort); + } + } + + + function socketOnXML(oXML){ + var oFirst=oXML.firstChild; + if( oFirst!=null && oFirst.attributes["room_url"]==this.sURL){ + var sRoomId = oFirst.attributes["room_id"]; + + for(var i=0;i"+oAuthorizeXML+""); + + if( !this.oConnection.sendMessage(oXML) ){ + this.callError("Can not send join-message."); + } + + } + + function sendMessage(oXML){ + if(oXML.firstChild!=null){ + if(oXML.firstChild.nodeName=="message"){ + oXML.firstChild.attributes["room_id"] = sIdentifier; + oXML.firstChild.attributes["room_url"] = this.oConnection.sURL; + + this.oConnection.sendMessage(oXML); + + }else{ + this.callError("Root-node in message must be \"message\""); + return false; + } + }else{ + this.callError("Empty XML"); + return false; + } + } + + private function callError(sError){ + trace(sError); + if(this.onError){ + this.onError(sError); + } + } + + function incommingMessage(oXML){ + var oFirst = oXML.firstChild; + switch(oFirst.nodeName){ + case "room:authorized": + this.sState = "authorized"; + this.iMyUserId = oFirst.attributes["user_id"]; + if(this.onJoin){ + this.onJoin( true ); + } + break; + case "room:unauthorized": + this.sState="unauthorized"; + if(this.onJoin){ + this.onJoin( false ); + } + break; + case "message": + if(this.onMessage){ + this.onMessage(oXML,this.getUser(oFirst.attributes["user_id"])); + } + break; + case "userlist": + this.updateUserlist(oFirst); + if(this.onUserChange){ + this.onUserChange(); + } + break; + } + } + + function getUser(iId){ + for(var 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 o3$@@QU8S@_^F6; + + + +example + + + + + + + + + + + + + + diff --git a/FlashAPI/example.swf b/FlashAPI/example.swf new file mode 100755 index 0000000000000000000000000000000000000000..f602143715f8985973ccbf1fa385da22a927af2b GIT binary patch literal 7768 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 literal 0 HcmV?d00001 diff --git a/FlashAPI/example_simple.as b/FlashAPI/example_simple.as new file mode 100755 index 0000000..6dbbc5e --- /dev/null +++ b/FlashAPI/example_simple.as @@ -0,0 +1,142 @@ + +oRoom=new XMLSocketd.Room("chat"); + +oRoom.onConnect = connected; +oRoom.onJoin = joinedRoom; +oRoom.onUserChange = updateUserList; +oRoom.onError = addLog; +oRoom.onMessage = message; + +oRoom.connect(); + +aMessages=new Array(); + +/***************************************************** +function connected + + Description: + Called when socket is connected or not + + Author: + 2005-03-22 Daniel Önnerby + +*****************************************************/ +function connected(bSuccess){ + if(bSuccess){ + addLog("Connected successfully"); + }else{ + addLog("Connected unsuccessfully"); + } +} + +/***************************************************** +function joinedRoom + + Description: + Called when user has tried to join the room + + Author: + 2005-03-22 Daniel Önnerby + +*****************************************************/ +function joinedRoom(bSuccess){ + if(bSuccess){ + addLog("Joined successfully"); + }else{ + addLog("Joined unsuccessfully"); + } +} + +/***************************************************** +function error + + Description: + Called on error + + Author: + 2005-03-22 Daniel Önnerby + +*****************************************************/ +function error(sError){ +} + + +/***************************************************** +function message + + Description: + Called when a message-xmltag has come in. + + Author: + 2005-03-22 Daniel Önnerby + +*****************************************************/ +function message( oXML,oUser ){ + for(var i=0;i"+oUser.oServerPreferences+":  "+oXML.firstChild.childNodes[i].firstChild+""; + } + } + renderTexts(); +} + + +/***************************************************** +function updateUserList + + Description: + Called when the userlist is updated + + Author: + 2005-03-22 Daniel Önnerby + +*****************************************************/ +function updateUserList(){ + var sList:String = ""; + for(var i=0;i=0;i--){ + sText+=_root.aMessages[i]+"
"; + } + _root["chat_text"].htmlText=sText; +} + + + +_root["inputtext"].onChanged=function (){ + var sMessage=_root["inputtext"].text; + if( sMessage.substr(sMessage.length-2)=="\r\r" ){ + _root["inputtext"].text=""; + sMessage=sMessage.substring(0,sMessage.length-2); + var oXML = new XML(""); + var oMessage = oXML.firstChild; + var oChat = oXML.createElement("chat"); + var oChatText = oXML.createTextNode(sMessage); + + oChat.appendChild(oChatText); + oMessage.appendChild(oChat); + + _root.oRoom.sendMessage(oXML); + + } +} \ No newline at end of file diff --git a/FlashAPI/join/index.php b/FlashAPI/join/index.php new file mode 100755 index 0000000..1ec189a --- /dev/null +++ b/FlashAPI/join/index.php @@ -0,0 +1,16 @@ + + + diff --git a/FlashAPI/whiteboard.as b/FlashAPI/whiteboard.as new file mode 100755 index 0000000..2c7d274 --- /dev/null +++ b/FlashAPI/whiteboard.as @@ -0,0 +1,64 @@ +oTempXML=new XML("test"); + +oRoom=new XMLSocketd.Room("whiteboard",oTempXML); +oRoom.onUserChange=updateUserList; +oRoom.onMessage=message; +oRoom.connect(); + +/* +function connected(bSuccess){ + if(bSuccess){ + addLog("Connected successfully"); + _root.oRoom=new XMLSocketd.Room(_root.oConnection); + _root.oRoom.onConnect=joinedRoom; + _root.oRoom.onUserChange=updateUserList; + _root.oRoom.onError=addLog; + _root.oRoom.onMessage=message; + _root.oRoom.join(); + }else{ + addLog("Connected unsuccessfully"); + } +} + +function joinedRoom(bSuccess){ + + if(bSuccess){ + addLog("Joined successfully"); + }else{ + addLog("Joined unsuccessfully"); + } + +} +*/ + +function message( oXML,oUser ){ + if(!oUser.isMe()){ + for(var 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 literal 0 HcmV?d00001 diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..f0cb04a --- /dev/null +++ b/Makefile @@ -0,0 +1,24 @@ +WARNINGS= -pedantic -Wall +LIBS = -pthread +CPPFLAGS= -O2 -DDEBUG #-fsave-memoized -fmemoize-lookups +CC=gcc +CPP=c++ +OBJS = src/main.o \ + src/server.o \ + src/user.o \ + src/xmlparser.o \ + src/message.o \ + src/room.o \ + src/httpconnection.o \ + src/authorizehttpconnection.o \ + src/stringqueue.o \ + src/roommember.o \ + src/player.o \ + src/Game.o + +BIN = xmlsocketd +main : $(OBJS) + $(CPP) $(CPPFLAGS) $(WARNINGS) $(OBJS) -o $(BIN) $(LIBS) + +clean : + rm -f *.o xmlsocketd src/*.o diff --git a/Makefile.win b/Makefile.win new file mode 100755 index 0000000..caebd25 --- /dev/null +++ b/Makefile.win @@ -0,0 +1,59 @@ +# Project: Flash XMLSocket Server +# Makefile created by Dev-C++ 4.9.9.1 + +CPP = g++.exe +CC = gcc.exe +WINDRES = windres.exe +RES = server_private.res +OBJ = src/server.o src/user.o src/main.o src/xmlparser.o src/httpconnection.o src/message.o src/room.o src/authorizehttpconnection.o src/stringqueue.o src/roommember.o $(RES) +LINKOBJ = src/server.o src/user.o src/main.o src/xmlparser.o src/httpconnection.o src/message.o src/room.o src/authorizehttpconnection.o src/stringqueue.o src/roommember.o $(RES) +LIBS = -L"C:/Dev-Cpp/lib" -L"C:/Dev-Cpp/the-agency/boost_1_31_0/the-agency/build/retail" C:/Dev-Cpp/lib/libws2_32.a C:/Dev-Cpp/lib/libpthreadGC.a -s -march=i686 +INCS = -I"C:/Dev-Cpp/include" +CXXINCS = -I"C:/Dev-Cpp/include/c++/3.3.1" -I"C:/Dev-Cpp/include/c++/3.3.1/mingw32" -I"C:/Dev-Cpp/include/c++/3.3.1/backward" -I"C:/Dev-Cpp/lib/gcc-lib/mingw32/3.3.1/include" -I"C:/Dev-Cpp/include" -I"C:/Dev-Cpp/the-agency/boost_1_31_0" +BIN = xmlsocketd.exe +CXXFLAGS = $(CXXINCS) -fexpensive-optimizations -O3 -march=i686 +CFLAGS = $(INCS) -fexpensive-optimizations -O3 -march=i686 + +.PHONY: all all-before all-after clean clean-custom + +all: all-before xmlsocketd.exe all-after + + +clean: clean-custom + rm -f $(OBJ) $(BIN) + +$(BIN): $(OBJ) + $(CPP) $(LINKOBJ) -o "xmlsocketd.exe" $(LIBS) + +src/server.o: src/server.cpp + $(CPP) -c src/server.cpp -o src/server.o $(CXXFLAGS) + +src/user.o: src/user.cpp + $(CPP) -c src/user.cpp -o src/user.o $(CXXFLAGS) + +src/main.o: src/main.cpp + $(CPP) -c src/main.cpp -o src/main.o $(CXXFLAGS) + +src/xmlparser.o: src/xmlparser.cpp + $(CPP) -c src/xmlparser.cpp -o src/xmlparser.o $(CXXFLAGS) + +src/httpconnection.o: src/httpconnection.cpp + $(CPP) -c src/httpconnection.cpp -o src/httpconnection.o $(CXXFLAGS) + +src/message.o: src/message.cpp + $(CPP) -c src/message.cpp -o src/message.o $(CXXFLAGS) + +src/room.o: src/room.cpp + $(CPP) -c src/room.cpp -o src/room.o $(CXXFLAGS) + +src/authorizehttpconnection.o: src/authorizehttpconnection.cpp + $(CPP) -c src/authorizehttpconnection.cpp -o src/authorizehttpconnection.o $(CXXFLAGS) + +src/stringqueue.o: src/stringqueue.cpp + $(CPP) -c src/stringqueue.cpp -o src/stringqueue.o $(CXXFLAGS) + +src/roommember.o: src/roommember.cpp + $(CPP) -c src/roommember.cpp -o src/roommember.o $(CXXFLAGS) + +server_private.res: server_private.rc + $(WINDRES) -i server_private.rc --input-format=rc -o server_private.res -O coff diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/gmon.out b/gmon.out new file mode 100755 index 0000000000000000000000000000000000000000..f1e1ea1de9fbdb4440c5c82d17899d1ead8c32be GIT binary patch literal 171632 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 Wj2rN!RVB~qvX@Ag-NG|fF8&K4c>>>>>> .r33 +LeftChar=1 +[Editor_10] +Open=0 +Top=0 +CursorCol=9 +CursorRow=14 +TopLine=1 +LeftChar=1 +[Editor_11] +Open=0 +Top=0 +CursorCol=1 +CursorRow=26 +TopLine=1 +LeftChar=1 +[Editor_12] +Open=0 +Top=0 +CursorCol=1 +CursorRow=11 +TopLine=6 +LeftChar=1 +[Editor_13] +Open=0 +Top=0 +CursorCol=38 +CursorRow=66 +TopLine=52 +LeftChar=1 +[Editor_14] +Open=0 +Top=0 +CursorCol=9 +CursorRow=18 +TopLine=1 +LeftChar=1 +[Editor_15] +Open=1 +Top=0 +CursorCol=34 +CursorRow=43 +TopLine=33 +LeftChar=1 +[Editor_16] +Open=0 +Top=0 +CursorCol=3 +CursorRow=36 +TopLine=9 +LeftChar=1 +[Editor_17] +Open=0 +Top=0 +CursorCol=1 +CursorRow=33 +TopLine=4 +LeftChar=1 +[Editor_18] +Open=0 +Top=0 +CursorCol=21 +CursorRow=33 +TopLine=2 +LeftChar=1 +[Editor_19] +Open=1 +Top=0 +CursorCol=1 +CursorRow=84 +TopLine=82 +LeftChar=1 +[Editor_20] +Open=0 +Top=0 diff --git a/src/Game.cpp b/src/Game.cpp new file mode 100644 index 0000000..69a4dc2 --- /dev/null +++ b/src/Game.cpp @@ -0,0 +1,135 @@ +using namespace std; + + +#include "player.h" +#include "user.h" + +#include "Game.h" + + +Game::Game(){ + +#ifdef DEBUG +// LOGSTREAM << "Server::Server\n"; +#endif + + + +} + +Game::~Game(){ + +#ifdef DEBUG +// LOGSTREAM << "Server::Server\n"; +#endif +// aPlayers = new std::vector(); +// aViewers = new std::vector(); + Yama.reserve(HAI_NUMBER); + +} + +void Game::start(){ + // start game; + + + + +} + +int Game::addPlayer(User* p){ + + +} + +void Game::initGame(){ + + int i; + std::random_shuffle( aPlayers.begin(), aPlayers.end()); + vector::iterator iPlayer = aPlayers.begin(); + for( i = 0; iPlayer < aPlayers.end(); iPlayer++){ + (*iPlayer)->setPoint(25000); + (*iPlayer)->setPos(i); + i++; + } +} + +void Game::newRound(){ + initYama(); + initDora(); + iCurrentPlayer = aPlayers.begin(); + + + +} + +//void Game::goStep(){ + + + + +// start from east; +//} + +void Game::dealHai(){ + (*iCurrentPlayer)->tsumo(*iYama++); + + +} + + + + +void Game::initDora(){ + Hai dora_show = Yama[DORA_SHOW_INDEX]; + + Dora.push_back((dora_show & 0xF0) | + (( dora_show & 0x0F + 1)%9)); + + + +} + +void Game::haipai(){ + /* + int i, j, k; + for( i = 0; i<3; i++){ + for( j = 0; j<4; j++) + // take four hai each time; + for( k = 0; k < 4; k++){ + aPlayers[j].haipai(*iYama); + iYama++; + } + } + + for( j = 0; j<4; j++){ + aPlayers[j].haipai(*iYama); + iYama++; + } + */ + int i; + vector::iterator iPlayer; + for( iPlayer = aPlayers.begin(); iPlayer< aPlayers.end(); iPlayer++){ + (*iPlayer)->haipai(iYama); + iYama += 13; + } +} + + +int myrandom( int i){ return std::rand()%i;} + +void Game::initYama(){ + + + std::copy(HaiData, HaiData + 136, Yama.begin()); + + random_shuffle(Yama.begin(),Yama.end(), myrandom); + + iYama = Yama.begin(); + +} + +void Game::handleAction(string userid , string action, string value){ + +} + + diff --git a/src/Game.h b/src/Game.h new file mode 100644 index 0000000..bfb2f86 --- /dev/null +++ b/src/Game.h @@ -0,0 +1,94 @@ +#ifndef _GAME_H_ +#define _GAME_H_ + + +#include +#include +#include +#include +#include +//#include +#include + +using namespace std; + + +enum { + HAI_NUMBER = 136, + DORA_SHOW_INDEX = 131, +}; + +enum state { + + EAST_TSUMO = 0x01, + SOUTH_TSUMO = 0x02, + WEST_TSUMO = 0x03, + NORTH_TSUMO = 0x04, + EAST_KIRU = 0x11, + SOUTH_KIRU = 0x12, + WEST_KIRU = 0x13, + NORTH_KIRU = 0x14, + OVER = 0x00, +}; + + +// Hai type unsigned char +const Hai HaiData[HAI_NUMBER] = { + // m + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, + // p + 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19, + 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19, + 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19, + 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19, + // s + 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29, + 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29, + 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29, + 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29, + // z + // east, south, west, north, chu, haku, hatsu + 0x31,0x32,0x33,0x34,0x35,0x36,0x37, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37, +}; + +//class Player; +//class User; +class Game{ +private: + vector aPlayers; + vector::iterator iCurrentPlayer; + vector Yama; + vector::iterator iYama; + vector Dora; + + int GameState; +//void haipai(class Player* p); + vector::iterator iLastTsumo; + void haipai(); + void dealHai(); + + +public: + Game(); + ~Game(); + + void handleAction(string, string, string); + int addPlayer(class User*); + void start(); + void initGame(); + void initYama(); + void newRound(); + void initDora(); + +}; + + + + +#endif diff --git a/src/authorizehttpconnection.cpp b/src/authorizehttpconnection.cpp new file mode 100755 index 0000000..63642bf --- /dev/null +++ b/src/authorizehttpconnection.cpp @@ -0,0 +1,97 @@ +using namespace std; +#include "config.h" +#include "user.h" +#include "room.h" +#include "roommember.h" +#include "stringqueue.h" +#include "xmlparser.h" +#include "authorizehttpconnection.h" +#include "server.h" + +extern StringQueue SQ; +extern pthread_mutex_t oHTTPThreadMutex; +extern pthread_cond_t oHTTPThreadCondition; + + +// class constructor +AuthorizeHTTPConnection::AuthorizeHTTPConnection(class RoomMember *oNewMember,class Server *oNewServer){ + #ifdef DEBUG + LOGSTREAM << "AuthorizeHTTPConnection::AuthorizeHTTPConnection()\n"; + #endif + bRemoved = false; + bFinished = false; + bDelete = false; + oMember = oNewMember; + oServer = oNewServer; +} + +// class destructor +AuthorizeHTTPConnection::~AuthorizeHTTPConnection(){ + +} + +bool AuthorizeHTTPConnection::authorize(){ + #ifdef DEBUG + LOGSTREAM << "AuthorizeHTTPConnection::authorize()\n"; + #endif + + sPOSTBuffer=""; + sPOSTBuffer.append("oRoom->sIdentifier); + sPOSTBuffer.append("\" user_ip=\""); + sPOSTBuffer.append(inet_ntoa(oMember->oUser->oSocketArrd.sin_addr)); + sPOSTBuffer.append("\" nof_users=\""); + + char sTemp[16]; + sprintf(sTemp,"%d",oMember->oRoom->aMembers.size()); + + sPOSTBuffer.append( sTemp ); + sPOSTBuffer.append("\">"); + sPOSTBuffer.append( oMember->sAuthorizeXML ); + sPOSTBuffer.append(""); + + std::string *sJoinURL = SQ.new_string(true); + sJoinURL->assign(oMember->oRoom->sURL+"/join/"); + + if( init(sJoinURL) ){ + return true; + }else{ + return false; + } +} + + +bool AuthorizeHTTPConnection::sendAuthorization(){ + #ifdef DEBUG + LOGSTREAM << "AuthorizeHTTPConnection::sendAuthorization\n"; + #endif + std::string sRead,sTemp; + std::string *sRootTag,*sNickName; + + if( getContent(sPOSTBuffer,&sRead) ){ + + if( oServer->oXMLParserThread.parse(&sRead) ){ + pthread_mutex_lock(&oHTTPThreadMutex); + if(!bRemoved){ + sRootTag = oServer->oXMLParserThread.getRootTag(); + if( *sRootTag=="room:authorized" ){ + bResultAuthorized = true; + sServerXML.swap(oServer->oXMLParserThread.sInnerXML); + }else{ + bResultAuthorized = false; + } + } + pthread_mutex_unlock(&oHTTPThreadMutex); + } + bFinished = true; + return true; + }else{ + + // Invalid respons from the webserver + bResultAuthorized = false; + bFinished = true; + return false; + } +} + + diff --git a/src/authorizehttpconnection.h b/src/authorizehttpconnection.h new file mode 100755 index 0000000..d9e7ab2 --- /dev/null +++ b/src/authorizehttpconnection.h @@ -0,0 +1,40 @@ +// Class automatically generated by Dev-C++ New Class wizard +#ifndef AUTHORIZEHTTPCONNECTION_H +#define AUTHORIZEHTTPCONNECTION_H + +#include +#include +#include +#include +#include + + +#include "httpconnection.h" // inheriting class's header file + +/* + * No description + */ +class AuthorizeHTTPConnection : public HTTPConnection{ + public: + // class constructor + AuthorizeHTTPConnection(class RoomMember *oNewMember,class Server *oNewServer); + // class destructor + ~AuthorizeHTTPConnection(); + + bool authorize(); + bool sendAuthorization(); + + RoomMember *oMember; + class Server *oServer; + bool bRemoved; + bool bFinished; + bool bDelete; + + bool bResultAuthorized; + std::string sServerXML; + + std::string sPOSTBuffer; + +}; + +#endif // AUTHORIZEHTTPCONNECTION_H diff --git a/src/config.h b/src/config.h new file mode 100755 index 0000000..990b5ca --- /dev/null +++ b/src/config.h @@ -0,0 +1,22 @@ +#define VERSION "0.2" + +#define PORT 2584 +#define SOCKETQUEUE 10 +#define MAINLOOPTIMEOUT 1 +#define READBUFFER_SIZE 4100 + +#define READBUFFER_MAX_SIZE 4096 +#define MAX_MESSAGE_QUEUE 16 + +// XMLParser +#define XMLTAGCHARS "abcdefghijklmnopqrstuvwxyz1234567890:_" +#define XMLATTRIBCHARS "abcdefghijklmnopqrstuvwxyz1234567890:_" + +// Logging +#ifndef _WIN32 + #define LOGSTREAM cout + #include +#else + #define LOGSTREAM cout +#endif + diff --git a/src/httpconnection.cpp b/src/httpconnection.cpp new file mode 100755 index 0000000..9b51753 --- /dev/null +++ b/src/httpconnection.cpp @@ -0,0 +1,143 @@ +using namespace std; + +#include "config.h" +#include "xmlparser.h" +#include "server.h" + +#include "httpconnection.h" + +HTTPConnection::HTTPConnection(){ + iPort = 80; + bValid = false; + bFinished = false; + iError = 0; + oServer = NULL; +} +HTTPConnection::HTTPConnection(std::string *sNewURL){ + iPort = 80; + bValid = false; + bFinished = false; + iError = 0; + init(sNewURL); +} + +HTTPConnection::~HTTPConnection(){ +} + +bool HTTPConnection::init(std::string *sNewURL){ + sURL=*sNewURL; + + int iTagHTTP=sURL.find("http://",0); + if(iTagHTTP!=string::npos){ + + // Find the domain end (next slash) + int iNextSlash=sURL.find("/",iTagHTTP+7); + if(iNextSlash==string::npos){ + iNextSlash=sURL.length(); + } + + sDomain=sURL.substr(iTagHTTP+7,iNextSlash-(iTagHTTP+7)); + + // Check for port + int iTagPort=sURL.find(":",iTagHTTP+7); + if(iTagPort!=string::npos){ + if(iTagPort0){ + iPort=iTempPort; + } + } + } + + // Find path + sPath=sURL.substr(iNextSlash); + + return true; + + }else{ + return false; + } +} + +bool HTTPConnection::getContent(std::string sPOST,std::string *sReadBuffer){ + + hostent *oHostName; + sockaddr_in oAddress; + + if( (iSocket = socket(AF_INET,SOCK_STREAM,0))==-1 ){ + cerr << "socket() error\n"; + return false; + } + + if( (oHostName=gethostbyname(sDomain.c_str()))==0 ) { + cerr << "gethostbyname error\n"; + return false; + } + oAddress.sin_family = AF_INET; + oAddress.sin_port = htons(iPort); + oAddress.sin_addr = *((in_addr *)oHostName->h_addr); + + if(connect(iSocket, (sockaddr *) &oAddress, sizeof(sockaddr))) { + cerr << "getContent error on connect\n"; + return false; + } + + urlEncode(sPOST); +// sPOST="xml="+sPOST; + char sContentLength[100]; + sprintf(sContentLength,"Content-length: %d",sPOST.length()); + + sendLine("POST "+sPath+" HTTP/1.0"); + sendLine("Host: "+sDomain); +// sendLine("Content-Type: application/x-www-form-urlencoded"); + sendLine( sContentLength ); + sendLine(""); + sendLine(sPOST); + sendLine(""); + + recieve(sReadBuffer); + + return true; +} + +void HTTPConnection::sendLine(std::string sLine){ + sLine+="\n"; + send(iSocket,sLine.c_str(),sLine.length(),0); +} + +void HTTPConnection::recieve(std::string *sBuffer){ + char sTemp[1025]; + int iRead=0; + do{ + iRead = recv(iSocket,sTemp,1024,0); + sBuffer->append(sTemp,iRead); + }while(iRead>0); + + +} + +bool HTTPConnection::urlEncode(std::string& sString){ + + static char hex[] = "0123456789ABCDEF"; + std::string sResult=""; + + for(int i = 0; i < sString.length(); i++){ + if(isalnum(sString[i])){ + sResult += sString[i]; + }else{ + if(sString[i] == ' '){ + sResult += '+'; + }else{ + sResult += '%'; + sResult += hex[sString[i] / 16]; + sResult += hex[sString[i] % 16]; + } + } + } + sString.swap(sResult); +} + + + diff --git a/src/httpconnection.h b/src/httpconnection.h new file mode 100755 index 0000000..8455e70 --- /dev/null +++ b/src/httpconnection.h @@ -0,0 +1,66 @@ +#ifndef HTTPCONNECTION_H +#define HTTPCONNECTION_H + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 + #include + #include + #define SHUT_RDWR 2 +#else + #include + #include + #include + #include +#endif + + +using namespace std; + + +class HTTPConnection{ + void sendLine(std::string sLine); + + public: + // class constructor + HTTPConnection(); + HTTPConnection(std::string *sNewURL); + + // class destructor + ~HTTPConnection(); + + bool init(std::string *sNewURL); + bool urlEncode(std::string& sString); + bool getContent(std::string sPOST,std::string *sReadBuffer); + void recieve(std::string *sBuffer); + + + public: + std::string sURL; + int iPort; + bool bValid; + bool bFinished; + std::string sDomain; + std::string sPath; + std::string sReadBuffer; + + int iSocket; + sockaddr_in oSocketArrd; + int iError; + + class Server *oServer; + +}; + +#endif + diff --git a/src/main.cpp b/src/main.cpp new file mode 100755 index 0000000..e3e0842 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,191 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#ifdef _WIN32 + #include + #include + #define SHUT_RDWR 2 +#else + #include + #include +#endif + + +using namespace std; + +#include "config.h" +#include "xmlparser.h" +#include "user.h" +#include "server.h" +#include "httpconnection.h" +#include "stringqueue.h" + +Server *oServer; +StringQueue SQ; +pthread_mutex_t oHTTPThreadMutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t oHTTPThreadCondition = PTHREAD_COND_INITIALIZER; +int iPort; + +void signalHandler(int iSignal){ +// oServer->exit(); + oServer->bExit=true; +} + +void *getURLThread(void *parameter){ + + oServer->waitForURLRequest(); + +} + + +int main(int argc, char *argv[]){ + iPort = PORT; + + // Read arguments + bool bUseLogFile=false; + for(int i=0;i"); + std::string *sAttribute; + + int iStartTime=clock(); + + for(int i=0;i<20000;i++){ + oParser.parse(&sString,&sTemp); + sAttribute = oParser.getAttribute("room_url"); + sTemp.swap(sString); + } + int iEndTime=clock(); + + cout << "Start time " << iStartTime << "\n"; + cout << "End time " << iEndTime << "\n"; + cout << "Total time " << (iEndTime-iStartTime) << "\n"; + return 0; +*/ + +/* + SocketClient oURL("onnerby.se",80); + oURL.SendLine("POST /~daniel/test3.php HTTP/1.0"); + oURL.SendLine("Host: onnerby.se"); + oURL.SendLine("Content-length: 15"); + oURL.SendLine(""); + oURL.SendLine("tjo=tjobbadobba"); + oURL.SendLine(""); + + + while (1) { + string l = oURL.ReceiveLine(); + if (l.empty()) break; + cout << l; + cout.flush(); + } + return 0; +*/ + #ifndef _WIN32 +// openlog("xmlsocketd",LOG_CONS|LOG_NOWAIT,LOG_DAEMON); + #endif + + + cout << "Starting server...\n"; + oServer = new Server(); + + if(!oServer){ + //cout << "ERROR: Can´t create Server-object\n"; + }else{ + + if(oServer->init()){ + + + pthread_t oThread; + pthread_attr_t oThreadAttrib; + int *parm=NULL; + int iRC=0; + iRC = pthread_attr_init(&oThreadAttrib); + if(iRC!=0){ + LOGSTREAM << "FAILED to pthread_attr_init with error " << iRC << "\n"; + return 1; + } + iRC = pthread_create(&oThread,NULL,getURLThread,(void *)parm); + if(iRC!=0){ + LOGSTREAM << "FAILED to pthread_create with error " << iRC << "\n"; + return 1; + } + + + signal( SIGINT, signalHandler ); + signal( SIGTERM, signalHandler ); + + oServer->mainLoop(); + void *oStatus; + pthread_join(oThread,&oStatus); + + delete oServer; + + #ifndef _WIN32 +// closelog(); + #endif + return 0; + }else{ + // Can't init the server + delete oServer; + #ifndef _WIN32 +// closelog(); + #endif + } + } + return 1; +} diff --git a/src/message.cpp b/src/message.cpp new file mode 100755 index 0000000..c771fae --- /dev/null +++ b/src/message.cpp @@ -0,0 +1,25 @@ +using namespace std; + +#include "config.h" + +#include "message.h" +#include "stringqueue.h" + +extern StringQueue SQ; + +// class constructor +Message::Message(string *sNewMessage){ + #ifdef DEBUG + LOGSTREAM << "Message::Message\n"; + #endif + sMessage = sNewMessage; + iNOFUsers = 0; +} + +// class destructor +Message::~Message(){ + #ifdef DEBUG + LOGSTREAM << "Message::~Message\n"; + #endif + SQ.delete_string(sMessage); +} diff --git a/src/message.h b/src/message.h new file mode 100755 index 0000000..910851c --- /dev/null +++ b/src/message.h @@ -0,0 +1,26 @@ + +#ifndef MESSAGE_H +#define MESSAGE_H + +#include +#include +#include +#include +#include + + +class Message +{ + public: + string *sMessage; + int iNOFUsers; + + public: + // class constructor + Message(string *sNewMessage); + // class destructor + ~Message(); + +}; + +#endif // MESSAGE_H diff --git a/src/player.cpp b/src/player.cpp new file mode 100644 index 0000000..fc2378d --- /dev/null +++ b/src/player.cpp @@ -0,0 +1,73 @@ +using namespace std; +#include "user.h" +#include "message.h" +#include "player.h" + + +Player::Player(){ +//#ifdef DEBUG +// LOGSTREAM << "Server::Server\n"; +//#endif + // do nothing + + Tehai.reserve(TEHAI_NUMBER); +} + +Player::~Player(){ + +} + +void Player::setPoint(int p){ + Point = p; +} +void Player::setPos(int p){ + Pos = p; +} +void Player::haipai(vector::iterator it){ + //std::copy(i, i+13, Tehai); + int i; + for(i = 0; i< 13; i++){ + Tehai.push_back(*(it+i)); + } + std::sort(Tehai.begin(), Tehai.end()); + + + + // generate xml message + // TODO + stringstream ss; + ss <<"::iterator itehai; + for(itehai = Tehai.begin(); itehai < Tehai.end(); itehai++){ + ss << std::hex << (*itehai); + } + ss <<"\" >\n"; + + p->sendMessage(new Message(new string(ss.str()))); +} +int checkTsumoState(){ + // check if can Agari or Kan or Riichi + return 0; +} + +void Player::tsumo(Hai h){ + TsumoHai = h; + + // generate xml message + + stringstream ss; + int state = checkTsumoState(); + + ss <<"\n"; + +} + + +//void Player::agari() + + +void Player::pon(Hai h){ + +} diff --git a/src/player.h b/src/player.h new file mode 100644 index 0000000..b3e5b64 --- /dev/null +++ b/src/player.h @@ -0,0 +1,57 @@ +#ifndef _PLAYER_H_ +#define _PLAYER_H_ + +#include +#include +#include +#include +#include +#include +using namespace std; + +enum { + TEHAI_NUMBER=13 +}; + + +// type of mahjong tile +typedef unsigned Hai; + +enum Position { + EAST = 0, + SOUTH = 1, + WEST = 2, + NORTH = 3, +}; + +using namespace std; +class Player{ +private: + class User *p; // connecting + string Name; + int Point; + vector Tehai; // tiles in hand + + bool Riichi; // Ready Hand declaration + int Pos; // EAST SOUTH WEST NORTH + char* Kawa; // river of discarded tiles + Hai TsumoHai; // the drew tile in this round + + +public: + Player(); + ~Player(); + void setPoint(int p); + void setPos(int p); + void haipai(vector::iterator ); + void tsumo(Hai h); + void pon(Hai h); + void chi(Hai h); + void kan(Hai h); + bool canAgari(); // win? + bool canKan(); + bool canRiichi(); + +}; + +#endif diff --git a/src/room.cpp b/src/room.cpp new file mode 100755 index 0000000..567e0b4 --- /dev/null +++ b/src/room.cpp @@ -0,0 +1,103 @@ +using namespace std; +#include "config.h" +#include "user.h" +#include "message.h" +#include "stringqueue.h" +#include "roommember.h" + +extern StringQueue SQ; + +#include "room.h" + +/***************************************************** +Room::Room + + Description: + Room object constructor + + Input: + *sRoomIdentifier = Room Identifier + *sRoomURL = Room URL + + Author: + 2005-03-01 Daniel Önnerby + +*****************************************************/ +Room::Room(string *sRoomIdentifier,string *sRoomURL){ + #ifdef DEBUG + LOGSTREAM << "Room::Room(" << *sRoomIdentifier << "," << *sRoomURL << ")\n"; + #endif + + sIdentifier = *sRoomIdentifier; + sURL = *sRoomURL; +} + +/***************************************************** +Room::~Room + + Description: + Class destructor + + Author: + 2005-03-01 Daniel Önnerby + +*****************************************************/ +Room::~Room(){ +} + +bool Room::sendMessage(Message *oMessage){ + #ifdef DEBUG + LOGSTREAM << "Room::sendMessage(" << (*oMessage->sMessage) << ")\n"; + #endif + vector::iterator oMember = aMembers.begin(); + for(; oMembersendMessage(oMessage) ){ + oMessage->iNOFUsers++; + } + } + + return (oMessage->iNOFUsers!=0); +} + +void Room::removeUser(User *oUser){ + #ifdef DEBUG + LOGSTREAM << "Room::removeUser(" << oUser->iSocket << ")\n"; + #endif + vector::iterator oCurrentMember = aMembers.begin(); + for(; oCurrentMemberoUser ){ + delete (*oCurrentMember); + oCurrentMember=aMembers.erase(oCurrentMember); + }else{ + oCurrentMember++; + } + } + + // Send deleted user to all other users + string *sMessage=SQ.new_string(); + sMessage->assign("sId+"\">\n"); + Message *oNewMessage=new Message(sMessage); + if( !sendMessage(oNewMessage) ){ + delete oNewMessage; + } +} + +bool Room::authorize(User *oUser,string *sAuthorizeXML){ + + // Check if user is already a member + vector::iterator oTempMember = aMembers.begin(); + while( oTempMember < aMembers.end() ){ + if( (*oTempMember)->oUser==oUser ){ + return false; + } + oTempMember++; + } + + RoomMember *oMember=new RoomMember(this,oUser,sAuthorizeXML); + + oUser->aMemberOf.push_back(oMember); + aMembers.push_back(oMember); + + return true; +} + diff --git a/src/room.h b/src/room.h new file mode 100755 index 0000000..b561115 --- /dev/null +++ b/src/room.h @@ -0,0 +1,34 @@ +#ifndef ROOM_H +#define ROOM_H + +#include +#include +#include +#include +#include + + + +class Room{ + public: + // class constructor + Room(string *sRoomIdentifier,string *sRoomURL); + // class destructor + ~Room(); + bool sendMessage(Message *oMessage); +// void join(User *oUser); + void removeUser(User *oUser); +// void unauthorized(User *oUser); + bool authorize(User *oUser,string *sAuthorizeXML); + + + string sIdentifier; + string sURL; + string sTitle; + string sCurrentJoinMessage; + int iId; + std::vector aMembers; + +}; + +#endif // ROOM_H diff --git a/src/roommember.cpp b/src/roommember.cpp new file mode 100755 index 0000000..d240291 --- /dev/null +++ b/src/roommember.cpp @@ -0,0 +1,121 @@ +using namespace std; +#include "config.h" +#include "xmlparser.h" +#include "server.h" +#include "user.h" +#include "room.h" +#include "message.h" +#include "stringqueue.h" +#include "authorizehttpconnection.h" + +extern StringQueue SQ; +extern pthread_mutex_t oHTTPThreadMutex; +extern pthread_cond_t oHTTPThreadCondition; +extern Server *oServer; + +#include "roommember.h" + + +RoomMember::RoomMember(class Room *oNewRoom,class User *oNewUser,string *sNewAuthorizeXML){ + #ifdef DEBUG + LOGSTREAM << "RoomMember::RoomMember " << (*sNewAuthorizeXML) << "\n"; + #endif + + oUser = oNewUser; + oRoom = oNewRoom; + + bAuthorized=false; + bDelete=false; + bAuthorizationOpen=true; + + sAuthorizeXML = *sNewAuthorizeXML; + oAuthorization = new AuthorizeHTTPConnection(this,oServer); + + if(!oAuthorization->authorize()){ + reject(); + }else{ + pthread_mutex_lock(&oHTTPThreadMutex); + oServer->aAuthorizeHTTPConnections.push_back( oAuthorization ); + pthread_cond_signal(&oHTTPThreadCondition); + pthread_mutex_unlock(&oHTTPThreadMutex); + } +} + +void RoomMember::reject(){ + #ifdef DEBUG + LOGSTREAM << "RoomMember::reject()\n"; + #endif + bAuthorized=false; + bDelete=true; + + if( !oUser->bDelete ){ + string *sMessage=SQ.new_string(); + sMessage->assign("sIdentifier+"\" room_url=\""+oRoom->sURL+"\">\n"); + + Message *oNewMessage=new Message(sMessage); + oNewMessage->iNOFUsers++; + oUser->sendMessage(oNewMessage); + } + +} + +bool RoomMember::authorized(){ + #ifdef DEBUG + LOGSTREAM << "RoomMember::authorized() " << oAuthorization->sServerXML << "\n"; + #endif + + sServerXML.swap(oAuthorization->sServerXML); + #ifdef DEBUG + LOGSTREAM << "SERVERXML " << sServerXML << "\n"; + #endif + + // Send to the client that it has been authorized + string *sMessage=SQ.new_string(); + sMessage->assign("sIdentifier+"\" room_url=\""+oRoom->sURL+"\" user_id=\""+oUser->sId+"\">"+sServerXML+"\n"); + + Message *oNewMessage=new Message(sMessage); + oNewMessage->iNOFUsers++; + oUser->sendMessage(oNewMessage); + + + // Send the new user to all other users + sMessage=SQ.new_string(); + sMessage->assign("sIdentifier+"\" room_url=\""+oRoom->sURL+"\">sId+"\">"+sServerXML+""+sUserXML+"\n"); + + oNewMessage=new Message(sMessage); + if( !oRoom->sendMessage(oNewMessage) ){ + delete oNewMessage; + } + + // Send the whole userlist to the new user + sMessage=SQ.new_string(); + sMessage->assign("sIdentifier+"\" room_url=\""+oRoom->sURL+"\">"); + + vector::iterator oCurrentMember = oRoom->aMembers.begin(); + for(; oCurrentMemberaMembers.end() ; oCurrentMember++ ){ + sMessage->append("oUser->sId+"\">"+(*oCurrentMember)->sServerXML+""+(*oCurrentMember)->sUserXML+"\n"); + } + + sMessage->append("\n"); + oNewMessage=new Message(sMessage); + oUser->sendMessage(oNewMessage); + + bAuthorized=true; +} + + +RoomMember::~RoomMember(){ + if(bAuthorizationOpen){ + oAuthorization->bDelete=true; + } +} + +// No description +bool RoomMember::sendMessage(class Message *oMessage){ + if( oUser->aOutgoingMessages.size() < MAX_MESSAGE_QUEUE && bAuthorized ){ + oUser->sendMessage(oMessage); + return true; + }else{ + return false; + } +} diff --git a/src/roommember.h b/src/roommember.h new file mode 100755 index 0000000..ef1d74f --- /dev/null +++ b/src/roommember.h @@ -0,0 +1,42 @@ +// Class automatically generated by Dev-C++ New Class wizard + +#ifndef ROOMMEMBER_H +#define ROOMMEMBER_H + +#include +#include +#include +#include +#include + + + +class RoomMember{ + + public: + // class constructor + RoomMember(class Room *oNewRoom,class User *oNewUser,string *sNewAuthorizeXML); + // class destructor + ~RoomMember(); + + bool sendMessage(class Message *oMessage); + bool authorized(); + void reject(); + + + public: + class AuthorizeHTTPConnection *oAuthorization; + bool bAuthorizationOpen; + + std::string sServerXML; + std::string sUserXML; + std::string sAuthorizeXML; + + class Room *oRoom; + class User *oUser; + bool bAuthorized; + bool bDelete; + +}; + +#endif // ROOMMEMBER_H diff --git a/src/server.cpp b/src/server.cpp new file mode 100755 index 0000000..91f610e --- /dev/null +++ b/src/server.cpp @@ -0,0 +1,668 @@ +using namespace std; + +#include "config.h" +#include "xmlparser.h" +#include "user.h" +#include "room.h" +#include "message.h" +#include "httpconnection.h" +#include "authorizehttpconnection.h" +#include "stringqueue.h" +#include "roommember.h" + +#include "server.h" + +extern StringQueue SQ; +extern pthread_mutex_t oHTTPThreadMutex; +extern pthread_cond_t oHTTPThreadCondition; +extern int iPort; + +/***************************************************** +Server::Server + + Description: + Default constructor + + Author: + 2004-10-13 Daniel Önnerby + +*****************************************************/ +Server::Server(){ + + #ifdef DEBUG + LOGSTREAM << "Server::Server\n"; + #endif + bExit=false; + iMaxSocket=0; + +} + + +/***************************************************** +Server::~Server + + Description: + Destructor + + Author: + 2004-10-13 Daniel Önnerby + +*****************************************************/ +Server::~Server(){ + #ifdef DEBUG + LOGSTREAM << "Server::~Server\n"; + #endif + + shutdown(iSocket, SHUT_RDWR); + #ifdef _WIN32 + closesocket(iSocket); + #else + close(iSocket); + #endif + +// pthread_mutex_destroy(&oHTTPThreadMutex); +// pthread_cond_destroy(&oHTTPThreadCondition); + +} + +/***************************************************** +Server::socketStartup + + Description: + Initialize the socket and start listening + + Returns: + + + Author: + 2004-10-13 Daniel Önnerby + +*****************************************************/ +bool Server::socketStartup(){ + #ifdef DEBUG + LOGSTREAM << "Server::socketStartup FD_SETSIZE=" << FD_SETSIZE << "\n"; + #endif + + #ifdef _WIN32 + WSADATA wsaData; + if(WSAStartup(MAKEWORD(1, 1), &wsaData)){ + cerr << "WSAStartup error\n"; + return false; + } + #endif + + if ((iSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + cerr << "Unable to create listener socket.\n"; + return false; + } + #ifdef DEBUG + LOGSTREAM << "LISTEN ON " << iSocket << "\n"; + #endif + + oListenerSocket.sin_family = AF_INET; + oListenerSocket.sin_port = htons(iPort); + oListenerSocket.sin_addr.s_addr = htonl(INADDR_ANY); + + // Bind the listener socket + if(bind(iSocket,(struct sockaddr *)&oListenerSocket,sizeof(struct sockaddr)) == -1) { + cerr << "Unable to bind listener socket.\n"; + return false; + } + + +#ifdef _EPOLL + if ( make_socket_non_blocking(iSocket) == -1){ + cerr << "Make nonblocking failed.\n"; + return false; + } +#endif + + + + // Try to listen on the socket + if( listen(iSocket,SOCKETQUEUE)==-1 ){ + cerr << "Unable to listen on the listener socket.\n"; + return false; + } + iMaxSocket = iSocket+1; + +#ifdef _EPOLL + if((epfd = epoll_create1(0)) == -1){ + cerr << "epoll create failed.\n"; + return false + + }; + + event.data.fd = iSocket; + event.events = EPOLLING | EPOLLET; + if ( epoll_ctl(epfd, EPOLL_CTL_ADD, iSocket, &event) == -1){ + cerr << "epoll register failed.\n"; + return false; + } + events = malloc(MAXEVENTS, sizeof event); +#endif + + + return true; + +} + +#ifdef _EPOLL +int make_socket_non_blocking (int sfd) +{ + int flags, s; + + flags = fcntl (sfd, F_GETFL, 0); + if (flags == -1) + { + perror ("fcntl"); + return -1; + } + + flags |= O_NONBLOCK; + s = fcntl (sfd, F_SETFL, flags); + if (s == -1) + { + perror ("fcntl"); + return -1; + } + + return 0; +} +#endif + + +/***************************************************** +Server::mainLoop + Description: + + + Returns: + + + Author: + 2004-10-13 Daniel Önnerby + +*****************************************************/ +bool Server::mainLoop(){ + #ifdef DEBUG + LOGSTREAM << "Server::mainLoop\n"; + #endif + + // declare variables + struct timeval oTimeout; + fd_set aReadResultSockets,aWriteResultSockets; + int iNewSocket=0; + int iNOFReadySockets=0; + + // Add the listener-socket + FD_ZERO(&aAllReadSockets); + FD_SET(iSocket,&aAllReadSockets); + + +/* +#ifdef _EPOLL + while(!bExit){ + int n, i; + if((n = epoll_wait(epfd, events, MAXEVENTS, -1)) == -1){ + cerr << "epoll wait error.\n"; + exit(EXIT_FAILURE); + }; + + for( i = 0; i < n; i++){ + + if ( events[i].events & EPOLLIN){ // read event + + if(iSocket = events[i].data.fd){ + // a new connection + sockaddr_in oNewClientSocket; + int iNewSocket; + +#ifdef _WIN32 + int iNewClientSocketLength = sizeof(oNewClientSocket); +#else + socklen_t iNewClientSocketLength = sizeof(oNewClientSocket); +#endif + if( (iNewSocket=accept(iSocket, einterpret_cast(&oNewClientSocket), &iNewClientSocketLength)) != -1 ){ + // New connection accepted + make_socket_non_blocking (iNewSocket); + + //register epoll event + + event.events = EPOLLIN | EPOLLET; + event.data.fd = iNewSocket; + if ( epoll_ctl(epfd, EPOLL_CTL_ADD, iNewSocket, &event) == -1){ + cerr << "epoll register failed.\n"; + return false; + } + + + // Create a new User in the aUsers-array + User* newUser = new User(this,iNewSocket,oNewClientSocket); + + aUsers.push_back(newUser); + //iGame.add(newUser); + aUsers.back()->sendMessage(new Message(new string("hello"))); + + // + + + + + if(iNewSocket>=iMaxSocket){ + iMaxSocket = iNewSocket+1; + } + }else{ + cerr << "Socket accept failed.\n"; + } + + } else { + // read data + + + } + } else if ( events[i].events & EPOLLOUT){ // write event + // flush write + + } else { + + // other eventskkk + } + + } + + }; + +#else +*/ + while(!bExit){ + + //Make a temporary fd_set as a copy of all the sockets + aReadResultSockets = aAllReadSockets; + aWriteResultSockets = aAllWriteSockets; + + // Set the timer every time (counts down on linux-systems but not on windows) + oTimeout.tv_sec=MAINLOOPTIMEOUT; + oTimeout.tv_usec=0; + if ( (iNOFReadySockets=select(iMaxSocket, &aReadResultSockets, &aWriteResultSockets, NULL, &oTimeout)) < 0){ + LOGSTREAM << "Socket select interupted\n"; + }else{ + + if(iNOFReadySockets!=0){ + + // Check if there are new connections waiting + if( FD_ISSET(iSocket,&aReadResultSockets) ){ + sockaddr_in oNewClientSocket; + int iNewSocket; + + #ifdef _WIN32 + int iNewClientSocketLength = sizeof(oNewClientSocket); + #else + socklen_t iNewClientSocketLength = sizeof(oNewClientSocket); + #endif + + + // Try to accept the new connection + if( (iNewSocket=accept(iSocket, reinterpret_cast(&oNewClientSocket), &iNewClientSocketLength)) != -1 ){ + + // New connection accepted + + // Create a new User in the aUsers-array + User* newUser = new User(this,iNewSocket,oNewClientSocket); + aUsers.push_back(newUser); + //iGame.add(newUser); + aUsers.back()->sendMessage(new Message(new string("Welcome\n"))); + + // + if(iNewSocket>=iMaxSocket){ + iMaxSocket = iNewSocket+1; + } + }else{ + cerr << "Socket accept failed.\n"; + } + iNOFReadySockets--; + } + + for(int i=0;ibDelete){ + delete aUsers[i]; + i--; + } + } + + // Check for writing sockets + vector::iterator oUser = aWriteUsers.begin(); + for(; oUser0; ){ + bool bEraseUserFromQueue=false; + if( FD_ISSET( (*oUser)->iSocket,&aWriteResultSockets) ){ + if(!(*oUser)->write()){ + // Remove the user from the aWriteUsers vector + bEraseUserFromQueue=true; + } + iNOFReadySockets--; + } + if(bEraseUserFromQueue){ + oUser=aWriteUsers.erase(oUser); + }else{ + oUser++; + } + } + + + // Check for reading + // vector::iterator oUser = aUsers.begin(); + oUser = aUsers.begin(); + for(; oUser0; oUser++){ + if( FD_ISSET( (*oUser)->iSocket,&aReadResultSockets) ){ + (*oUser)->read(sSocketReadBuffer); + iNOFReadySockets--; + } + } + + }else{ + + // I got a timeout, lets do some cleanup + cleanUp(); + } + + + // Check for finished authorizations + if( pthread_mutex_trylock(&oHTTPThreadMutex)==0 ){ + vector::iterator oConnection = aAuthorizeHTTPConnections.begin(); + while( oConnectionbFinished && !(*oConnection)->bRemoved && !(*oConnection)->bDelete ){ + if( (*oConnection)->bResultAuthorized ){ + (*oConnection)->oMember->authorized(); + }else{ + (*oConnection)->oMember->reject(); + } + } + + if( (*oConnection)->bFinished || (*oConnection)->bRemoved ){ + (*oConnection)->bDelete=true; + } + + oConnection++; + } + pthread_mutex_unlock(&oHTTPThreadMutex); + } + + } + + } + +//#endif // ifdef _EPOLL + + + this->exit(); + // clear all users from the arrays + while( !aUsers.empty() ){ + User *oTempUser=aUsers.back(); + delete oTempUser; + } + + vector::iterator oRoom = aRooms.begin(); + // clear all elements from the array + for(; oRoom::iterator oUser = aUsers.begin(); + + // clear all elements from the array + for(; oUserbDelete){ + delete *oUser; + aUsers.erase(oUser); + } + } +*/ +} + +/***************************************************** +Server::sendToRoom + + Description: + Sends a message to all users in a room + The function also manipulates the root-tag + attributes and adds room_id room_url and user_id + + Input: + *oMessage = Message to be send + *sRoomIdentifier = Rooms identifier + *sRoomURL = Rooms base URL + *oUser = User who is sending the message + + Author: + 2004-10-13 Daniel Önnerby + +*****************************************************/ +bool Server::sendToRoom(class Message *oMessage,string *sRoomIdentifier,string *sRoomURL,User *oUser){ + + int iFirstTag,iLastTag; + string sTemp; + + if( (*oMessage->sMessage)!="" ){ + + vector::iterator oMember = oUser->aMemberOf.begin(); + for(; oMemberaMemberOf.end(); oMember++){ + if( (*oMember)->oRoom->sIdentifier == *sRoomIdentifier && (*oMember)->oRoom->sURL == *sRoomURL ){ + + // Add root-tag with attributes + oMessage->sMessage->insert(0,"<"+*(oXMLParser.getRootTag())+" room_id=\""+*sRoomIdentifier+"\" room_url=\""+*sRoomURL+"\" user_id=\""+oUser->sId+"\">"); + oMessage->sMessage->append(""); + + return (*oMember)->oRoom->sendMessage(oMessage); + } + } + return false; + }else{ + #ifdef DEBUG + LOGSTREAM << "Server::sendToRoom empty message send " << iFirstTag << " " << iLastTag << "\n"; + #endif + return false; + } + + +} + +/***************************************************** +Server::joinRoom + + Description: + Locates or creates the room and tries to join + + Input: + *oUser = The User + *sRoomIdentifier = Rooms identifier + *sRoomURL = Rooms base URL + *sLogin = Users login for the room in question + *sPassword = Users password for the room in question + + Author: + 2005-03-01 Daniel Önnerby + +*****************************************************/ +bool Server::joinRoom(class User *oUser,string *sRoomIdentifier,string *sRoomURL,string *sAuthorizationXML){ + #ifdef DEBUG + LOGSTREAM << "Server::joinRoom " << (*sRoomIdentifier) << "\n"; + #endif + + vector::iterator oRoom = aRooms.begin(); + for(; oRoomsIdentifier == *sRoomIdentifier ){ + if( (*oRoom)->sURL == *sRoomURL ){ + // Room found, try to authorize + return (*oRoom)->authorize(oUser,sAuthorizationXML); + } + } + } + + // Room not found, create the room + Room *oNewRoom = new Room(sRoomIdentifier,sRoomURL); + aRooms.push_back(oNewRoom); + + // Authorize + return oNewRoom->authorize(oUser,sAuthorizationXML); +} + + +/***************************************************** +Server::joinRoomAuthorize + + Description: + Add the user to the queue for authorization + + Input: + *oUser = The User + *oRoom = Room + *sLogin = Users login for the room in question + *sPassword = Users password for the room in question + + + Author: + 2005-03-01 Daniel Önnerby + +*****************************************************/ +/*bool Server::joinRoomAuthorize(class User *oUser,class Room *oRoom,string *sAuthorizationXML){ + + // Check if user is already a member + vector::iterator oTempUser = oRoom->aUsers.begin(); + while( oTempUseraUsers.end()){ + if( (*oTempUser)== oUser ){ + return false; + } + oTempUser++; + } + + + AuthorizeHTTPConnection *oNewConnection = new AuthorizeHTTPConnection(oUser,oRoom,this); + oNewConnection->authorize(sLogin,sPassword); + + pthread_mutex_lock(&oHTTPThreadMutex); + aAuthorizeHTTPConnections.push_back( oNewConnection ); + pthread_cond_signal(&oHTTPThreadCondition); + pthread_mutex_unlock(&oHTTPThreadMutex); + + return true; +} +*/ +/***************************************************** +Server::waitForURLRequest + + Description: + + + Input: + + + Author: + 2005-03-01 Daniel Önnerby + +*****************************************************/ +bool Server::waitForURLRequest(){ + int iRC=0; + while(!bExit){ + + pthread_mutex_lock(&oHTTPThreadMutex); + iRC=pthread_cond_wait(&oHTTPThreadCondition,&oHTTPThreadMutex); + + AuthorizeHTTPConnection *oTempConnection; + + vector::iterator oConnection = aAuthorizeHTTPConnections.begin(); + while( oConnectionbDelete ){ + delete (*oConnection); + oConnection = aAuthorizeHTTPConnections.erase(oConnection); + }else{ + if( !(*oConnection)->bFinished ){ + pthread_mutex_unlock(&oHTTPThreadMutex); + (*oConnection)->sendAuthorization(); + pthread_mutex_lock(&oHTTPThreadMutex); + } + oConnection++; + } + + + } + + pthread_mutex_unlock(&oHTTPThreadMutex); + } + +} + diff --git a/src/server.h b/src/server.h new file mode 100755 index 0000000..731c2b1 --- /dev/null +++ b/src/server.h @@ -0,0 +1,75 @@ +#ifndef _SERVER_H_ +#define _SERVER_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef _WIN32 + #include + #include + #define SHUT_RDWR 2 +#else + #include + #include + #include +#endif + + +#define MAXEVENTS 64 + +using namespace std; + +class Server { + public: + Server(); + ~Server(); + + bool socketStartup(); + bool mainLoop(); + bool init(); + void exit(); + void cleanUp(); + bool joinRoom(class User *oUser,string *sRoomIdentifier,string *sRoomURL,string *sAuthorizationXML); +// bool joinRoomAuthorize(class User *oUser,class Room *oRoom,string *sAuthorizationXML); + bool sendToRoom(class Message *oMessage,string *sRoomIdentifier,string *sRoomURL,User *oUser); + bool waitForURLRequest(); + + public: + + bool bExit; + XMLParser oXMLParser; + XMLParser oXMLParserThread; + char sSocketReadBuffer[READBUFFER_SIZE]; + + int iSocket; + int iMaxSocket; + #ifdef _EPOLL + int epfd; + struct epoll_event event; + struct epoll_event *events; + #endif + struct sockaddr_in oListenerSocket; + fd_set aAllReadSockets; + fd_set aAllWriteSockets; + + + + std::vector aWriteUsers; + std::vector aUsers; + std::vector aRooms; + std::vector aAuthorizeHTTPConnections; + +}; + +#endif + diff --git a/src/server_private.h b/src/server_private.h new file mode 100755 index 0000000..1c60bc0 --- /dev/null +++ b/src/server_private.h @@ -0,0 +1,23 @@ +// THIS FILE WILL BE OVERWRITTEN BY DEV-C++! +// DO NOT EDIT! + +#ifndef SERVER_PRIVATE_H +#define SERVER_PRIVATE_H + +// VERSION DEFINITIONS +#define VER_STRING "0.1.1.22" +#define VER_MAJOR 0 +#define VER_MINOR 1 +#define VER_RELEASE 1 +#define VER_BUILD 22 +#define COMPANY_NAME "" +#define FILE_VERSION "" +#define FILE_DESCRIPTION "Flash XMLSocket Server" +#define INTERNAL_NAME "" +#define LEGAL_COPYRIGHT "GPL Licens" +#define LEGAL_TRADEMARKS "" +#define ORIGINAL_FILENAME "" +#define PRODUCT_NAME "Flash XMLSocket Server" +#define PRODUCT_VERSION "" + +#endif //SERVER_PRIVATE_H diff --git a/src/stringqueue.cpp b/src/stringqueue.cpp new file mode 100755 index 0000000..2eb3b7e --- /dev/null +++ b/src/stringqueue.cpp @@ -0,0 +1,55 @@ +using namespace std; + +#include "config.h" +#include "stringqueue.h" // class's header file + +// class constructor +StringQueue::StringQueue(){ + iNOFStrings=0; +} + +// class destructor +StringQueue::~StringQueue(){ + std::string *sTemp; + while(!aQueue.empty()){ + sTemp = aQueue.top(); + delete sTemp; + aQueue.pop(); + } +} + +std::string *StringQueue::new_string(bool bClear=false){ + if(iNOFStrings!=0){ + std::string *sString=aQueue.top(); + aQueue.pop(); + iNOFStrings--; + if(bClear){ + sString->assign(""); + } + return sString; + }else{ + return (new string()); + } +} + +std::string *StringQueue::new_string(){ + if(iNOFStrings!=0){ + std::string *sString=aQueue.top(); + aQueue.pop(); + iNOFStrings--; + return sString; + }else{ + return (new string()); + } +} + +void StringQueue::delete_string(std::string *sString){ + if( iNOFStrings>=MAX_STRING_QUEUE || sString->size()>READBUFFER_SIZE ){ + delete sString; + }else{ + aQueue.push(sString); + iNOFStrings++; + } +} + + diff --git a/src/stringqueue.h b/src/stringqueue.h new file mode 100755 index 0000000..826d780 --- /dev/null +++ b/src/stringqueue.h @@ -0,0 +1,32 @@ + +#ifndef STRINGQUEUE_H +#define STRINGQUEUE_H + +#include +#include +#include +#include +#include + +#define MAX_STRING_QUEUE 20 +/* + * No description + */ +class StringQueue +{ + public: + // class constructor + StringQueue(); + // class destructor + ~StringQueue(); + + std::string *new_string(bool bClear); + std::string *new_string(); + void delete_string(std::string *sString); + + std::stack aQueue; + int iNOFStrings; + +}; + +#endif // STRINGQUEUE_H diff --git a/src/user.cpp b/src/user.cpp new file mode 100755 index 0000000..3f5b4ed --- /dev/null +++ b/src/user.cpp @@ -0,0 +1,380 @@ +using namespace std; + +#include "config.h" +#include "xmlparser.h" +#include "server.h" +#include "message.h" +#include "room.h" +#include "stringqueue.h" +#include "authorizehttpconnection.h" +#include "roommember.h" + +extern StringQueue SQ; +extern pthread_mutex_t oHTTPThreadMutex; +extern pthread_cond_t oHTTPThreadCondition; + +#include "user.h" + +/***************************************************** +User::User + + Description: + Default constructor (never used) + + Author: + 2004-10-13 Daniel Önnerby + +*****************************************************/ +User::User(){ + +} + +/***************************************************** +User::User(int iNewSocket,sockaddr_in oNewSocketArrd) + + Description: + Constructor used to submit the socketinformation + + Author: + 2004-10-13 Daniel Önnerby + +*****************************************************/ +User::User(class Server *oMainServer,int iNewSocket,sockaddr_in oNewSocketArrd){ + #ifdef DEBUG + LOGSTREAM << "User::User(oMainServer," << iNewSocket << ",oNewSocketArrd)\n"; + #endif + bWriting = false; + bNameLock = false; + iCurrentMsgWritten = 0; + oServer = oMainServer; + iSocket = iNewSocket; + oSocketArrd = oNewSocketArrd; + +// LOGSTREAM << "Connection from " << inet_ntoa(oSocketArrd.sin_addr) << " - " << iSocket << "\n"; + + bDelete = !initSocket(); + + if(!bDelete){ + FD_SET(iSocket,&oServer->aAllReadSockets); + char sTemp[16]; + sprintf(sTemp,"%d",iSocket); + sId.append(sTemp); + } + +} + + +/***************************************************** +User::~User + + Description: + Destructor + + Author: + 2004-10-13 Daniel Önnerby + +*****************************************************/ +User::~User(){ + #ifdef DEBUG + LOGSTREAM << "User::~User()\n"; + #endif + //LOGSTREAM << "Dropped " << inet_ntoa(oSocketArrd.sin_addr) << " - " << iSocket << "\n"; + + FD_CLR (iSocket, &oServer->aAllReadSockets); + FD_CLR (iSocket, &oServer->aAllWriteSockets); + + // Remove possible Authorizations from queue + pthread_mutex_lock(&oHTTPThreadMutex); + vector::iterator oAuthorize = oServer->aAuthorizeHTTPConnections.begin(); + for(; oAuthorizeaAuthorizeHTTPConnections.end(); oAuthorize++){ + if((*oAuthorize)->oMember->oUser==this){ + (*oAuthorize)->bRemoved=true; + } + } + pthread_mutex_unlock(&oHTTPThreadMutex); + + + + // Remove from rooms + vector::iterator oMember = aMemberOf.begin(); + for(; oMemberoRoom->removeUser(this); + } + + // Remove messages + while(!aOutgoingMessages.empty()){ +/* Message *oMessage = aOutgoingMessages.front(); + oMessage->iNOFUsers--; + if(oMessage->iNOFUsers<=0){ + delete oMessage; + }*/ + removeMessage(aOutgoingMessages.front()); + aOutgoingMessages.pop(); + } + + + // Remove from main userlist + vector::iterator oTempUser = oServer->aUsers.begin(); + while( oTempUser< oServer->aUsers.end() ){ + if( (*oTempUser)->iSocket==iSocket ){ + oTempUser = oServer->aUsers.erase(oTempUser); + }else{ + oTempUser++; + } + } + + // Remove from writing userlist + oTempUser = oServer->aWriteUsers.begin(); + while( oTempUser< oServer->aWriteUsers.end() ){ + if( (*oTempUser)->iSocket==iSocket ){ + oTempUser = oServer->aWriteUsers.erase(oTempUser); + }else{ + oTempUser++; + } + } + + +// shutdown(iSocket,SHUT_RDWR); + close(iSocket); +} + +bool User::operator==(User *oUser){ + return iSocket==oUser->iSocket; +} + +bool User::operator==(int iUserSocket){ + return iSocket==iUserSocket; +} + + +/***************************************************** +User::initSocket + + Description: + Sets the socket to nonblocking + + Returns: + true on success + + Author: + 2004-10-13 Daniel Önnerby + +*****************************************************/ +bool User::initSocket(){ + #ifdef DEBUG + LOGSTREAM << "User::initSocket()\n"; + #endif + + int iError=0; + + // Setting NONBLOCKING + #ifdef _WIN32 + unsigned long tmp = 1; + if((iError=ioctlsocket(iSocket, FIONBIO, &tmp)) == SOCKET_ERROR){ + cerr << "ERROR: ioctlsocket " << iError << "\n"; + return false; + } + #else + if((iError=fcntl(iSocket, F_SETFL, O_NONBLOCK))!=0){ + cerr << "ERROR: fcntl " << iError << "\n"; + return false; + } + #endif + + return true; +} +/***************************************************** +User::read + + Description: + + Author: + 2004-10-13 Daniel Önnerby + +*****************************************************/ +bool User::read(char *sBuffer){ + + int iBytesRead=0; + + if(sReadBuffer.length()oXMLParser.parse(&sReadBuffer) ){ + //Everything is ok. Check for message. +#ifdef DEBUG + LOGSTREAM << "Valid message send\n"; +#endif + + string type = oServer->oXMLParser.aXMLPath[0]; + + if( type =="message" ){ + + // A chat message is send + sNewMessage->swap(oServer->oXMLParser.sInnerXML); + + Message *oNewMessage = new Message(sNewMessage); + LOGSTREAM <<"sNewMessage: "<<*sNewMessage<sendToRoom(oNewMessage,oServer->oXMLParser.getAttribute("room_id"),oServer->oXMLParser.getAttribute("room_url"),this ) ){ + // If the message can not be send, delete it. + delete oNewMessage; + } + + + }else if(type== "game" ){ +// string haipai = oServer->oXMLParser.getAttribute("join"); +// LOGSTREAM << "haipai" << haipai; + + // parse haipai; + + + + + }else{ + SQ.delete_string(sNewMessage); + if(type=="room:join" ){ + + if(!oServer->joinRoom(this, + oServer->oXMLParser.getAttribute("room_id"), + oServer->oXMLParser.getAttribute("room_url"), + &oServer->oXMLParser.sInnerXML) ){ + + // Unable to join room, drop the user + // This will never happen in the current state + //bDelete=true; + //return false; + } + + this->sendMessage(new Message(new string("welcome to game1\n"))); + + }else{ +/* if( oServer->oXMLParser.aXMLPath[0]=="system:setname" ){ + // Set the name if it is not locked + if( !bNameLock ){ + #ifdef DEBUG + LOGSTREAM << "Username set to " << *(oServer->oXMLParser.getAttribute("name")) << "\n"; + #endif + sName = *(oServer->oXMLParser.getAttribute("name")); + } + }else{*/ + if(sReadBuffer.length()>READBUFFER_MAX_SIZE){ + + // Buffer to big, drop the user. + + + bDelete=true; + return false; + } +// } + } + + } + return true; + }else{ + SQ.delete_string( sNewMessage ); + + // Output is not finished or something went wrong + if(sReadBuffer.length()>READBUFFER_MAX_SIZE){ + #ifdef DEBUG + LOGSTREAM << "DELETE User::interpretBuffer 2 length=" << sReadBuffer.length() << " \n"; + #endif + bDelete=true; + } + return false; + } + +} + +void User::sendMessage(class Message *oMessage){ + #ifdef DEBUG + LOGSTREAM << "User::sendMessage(" << *oMessage->sMessage << ")\n"; + #endif + if(!bWriting){ + FD_SET(iSocket,&oServer->aAllWriteSockets); + oServer->aWriteUsers.push_back(this); + bWriting=true; + } + aOutgoingMessages.push(oMessage); +} + +bool User::write(){ + #ifdef DEBUG + LOGSTREAM << "User::write()\n"; + #endif + Message *oMessage = aOutgoingMessages.front(); + + int iLength = oMessage->sMessage->length()+1; + int iWritten=send( iSocket,oMessage->sMessage->c_str()+iCurrentMsgWritten,iLength-iCurrentMsgWritten,0); + + + if(iWritten==-1){ + #ifdef DEBUG + LOGSTREAM << "DELETE User::write SEND failed with -1\n"; + #endif + bDelete=true; + } + + iCurrentMsgWritten+=iWritten; + if(iCurrentMsgWritten>=iLength-1){ +/* oMessage->iNOFUsers--; + if(oMessage->iNOFUsers<=0){ + delete oMessage; + }*/ + removeMessage(oMessage); + + aOutgoingMessages.pop(); + iCurrentMsgWritten=0; + if(aOutgoingMessages.size()==0){ + + // Queue is empty. Remove writing socket etc. + FD_CLR(iSocket, &oServer->aAllWriteSockets); + bWriting=false; + return false; + } + } + return true; +} + + +bool User::removeMessage(Message *oMessage){ + oMessage->iNOFUsers--; + if(oMessage->iNOFUsers<=0){ + delete oMessage; + return true; + } + return false; +} diff --git a/src/user.h b/src/user.h new file mode 100755 index 0000000..249221a --- /dev/null +++ b/src/user.h @@ -0,0 +1,64 @@ +#ifndef _USER_H_ +#define _USER_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 + #include + #include + #define SHUT_RDWR 2 +#else + #include + #include + #include + #include +#endif + + + +class User{ + public: + User(); + User(int iNewSocket,sockaddr_in oNewSocketArrd); + User(class Server *oMainServer,int iNewSocket,sockaddr_in oNewSocketArrd); + bool initSocket(); + ~User(); + bool read(char *sBuffer); + bool write(); + bool interpretBuffer(); + void sendMessage(class Message *oMessage); + bool operator==(User *oUser); + bool operator==(int iUserSocket); + + string sName; + bool bNameLock; + string sId; + string sUserXML; + string sReadBuffer; + + std::queue aOutgoingMessages; + int iCurrentMsgWritten; + bool bWriting; + + std::vector aMemberOf; + + bool bDelete; + class Server *oServer; + + int iSocket; + sockaddr_in oSocketArrd; + // No description + bool removeMessage(Message *oMessage); + +}; + +#endif diff --git a/src/xmlparser.cpp b/src/xmlparser.cpp new file mode 100755 index 0000000..418bfdb --- /dev/null +++ b/src/xmlparser.cpp @@ -0,0 +1,226 @@ +using namespace std; + +#include "config.h" + +#include "xmlparser.h" // class's header file + +/***************************************************** +XMLParser::XMLParser + + Description: + Constructor + + Author: + 2004-10-13 Daniel Önnerby + +*****************************************************/ +XMLParser::XMLParser(){ + + sEmptyString=""; +} + +/***************************************************** +XMLParser::~XMLParser + + Description: + Destructor + + Author: + 2004-10-13 Daniel Önnerby + +*****************************************************/ +XMLParser::~XMLParser(){ + aXMLPath.clear(); +// aAttributes.clear(); + +} + +/***************************************************** +XMLParser::parse + + Description: + Parse a string to XML + + Author: + 2004-10-13 Daniel Önnerby + +*****************************************************/ +bool XMLParser::parse(string *sXML){ + int iCurrentPos=0; + int iXMLLength=sXML->length(); + int iFoundStart; + int iFoundEnd; + int iInnerStart; + int iInnerEnd; + bool bFound; + bool bAnyTags=false; + string sCurrentTag=""; + + int iXMLTagPos=0; + + do{ + bFound=false; + iFoundStart=sXML->find("<",iCurrentPos); + if(iFoundStart!=string::npos){ + // Found start-tag + iFoundEnd=sXML->find(">",iFoundStart+1); + if(iFoundEnd!=string::npos){ + + // Found end of the tag-tag + if(sXML->at(iFoundStart+1)=='/' ){ + + // XML End-tag + sCurrentTag = sXML->substr( + iFoundStart+2, + sXML->find_first_not_of(XMLTAGCHARS,iFoundStart+2)-iFoundStart-2 + ); + + if(aXMLPath[iXMLTagPos-1]==sCurrentTag){ + // This was the current tag. End it. + iXMLTagPos--; + } + }else{ + int iEndOfTag=sXML->find_first_not_of(XMLTAGCHARS,iFoundStart+1); + // Start tag + if(aXMLPath.size()<=iXMLTagPos){ + // If the array is to small + aXMLPath.push_back(sXML->substr(iFoundStart+1,iEndOfTag-iFoundStart-1)); + }else{ + // Already exists + aXMLPath[iXMLTagPos]=sXML->substr(iFoundStart+1,iEndOfTag-iFoundStart-1); + } + + if( sXML->at(iFoundEnd-1)!='/' ){ + // Do not increase if it's a short tag that closes itself + iXMLTagPos++; + } + if(!bAnyTags){ + // If this is the first tag, then get the attributes + getAttributes(sXML,iEndOfTag,iFoundEnd-1); + iInnerStart=iFoundEnd+1; + bAnyTags=true; + } + } + iCurrentPos=iFoundEnd+1; + bFound=true; + } + } + }while(bFound && (!bAnyTags || iXMLTagPos!=0) ); + + if(bAnyTags && iXMLTagPos==0){ + + // Inner XML + iInnerEnd=iFoundStart-1; + + int iNextMessage=sXML->find("<",iCurrentPos); + if(iNextMessage==string::npos ){ + sOuterXML=""; + sOuterXML.swap(*sXML); + }else{ + sOuterXML = sXML->substr(iNextMessage); + sXML->erase(iCurrentPos); + sXML->swap(sOuterXML); + } + + if(iInnerEnd<=iInnerStart){ + sInnerXML=""; + }else{ + sInnerXML = sOuterXML.substr(iInnerStart,iInnerEnd-iInnerStart+1); + } + + } + + return bAnyTags && iXMLTagPos==0; +} + +/***************************************************** +XMLParser::parse + + Description: + Parse a string to XML + + Author: + 2004-10-13 Daniel Önnerby + +*****************************************************/ +void XMLParser::getAttributes(string *sXML,int iCurrentPos,int iEndAttrib){ + + bool bFound=false; + aAttributes.clear(); + aAttributeValues.clear(); + + do{ + bFound=false; + + // Find start attribute char + int iAttribStart = sXML->find_first_of(XMLATTRIBCHARS,iCurrentPos); + if(iAttribStart!=string::npos && iAttribStartfind_first_not_of(XMLATTRIBCHARS,iAttribStart); + if(iAttribEnd!=string::npos){ + + // Check for the =-sign + if( sXML->at(iAttribEnd)=='=' ){ + + // Find value + int iEndAttribValue=sXML->find_first_of("\">",iAttribEnd+2); + if( iEndAttribValue!=string::npos ){ + + aAttributes.push_back(sXML->substr(iAttribStart,iAttribEnd-iAttribStart)); + aAttributeValues.push_back(sXML->substr(iAttribEnd+2,iEndAttribValue-iAttribEnd-2)); + + bFound=true; + iCurrentPos=iEndAttribValue+1; + } + + } + + } + } + + }while( bFound ); + + +} + + +/***************************************************** +XMLParser::getAttribute + + Description: + Parse the attributes of the first tag from the XML + + Author: + 2004-10-13 Daniel Önnerby + +*****************************************************/ +string *XMLParser::getAttribute(const char *sAttribute){ + + vector::iterator sCurrentAttribute = aAttributes.begin(); + int i=0; + for(; sCurrentAttribute +#include +#include +#include +#include +#include + + +class XMLParser{ + public: + // class constructor + XMLParser(); + // class destructor + ~XMLParser(); + + bool parse(string *sXML); + string sEmptyString; + string sInnerXML; + string sOuterXML; + + string *getAttribute(const char *sAttribute); + + public: + void getAttributes(string *sXML,int iCurrentPos,int iEndAttrib); + string *getRootTag(); + + // Variables + public: + vector aXMLPath; + + + // Variables + private: + vector aAttributes,aAttributeValues; +}; + +#endif // XMLPARSER_H + diff --git a/xmlsocketd.prj b/xmlsocketd.prj new file mode 100755 index 0000000..f8acfc4 --- /dev/null +++ b/xmlsocketd.prj @@ -0,0 +1,236 @@ +[Project ID] +Signature=UE Proj: v.1 +[Tools] +Tool Cmd0="C:\Dev-Cpp\bin\make.exe clean" +Tool Dir0="%r" +Tool Menu0="clean" +Bitmap Path0="" +Show DOS Window0=0 +Capture0=1 +Capture Mode0=3 +WinProg0=1 +SaveAllFiles0=1 +Save Active File0=1 +Replace Type0=0 +Tool Cmd1="C:\Dev-Cpp\bin\make.exe" +Tool Dir1="%r" +Tool Menu1="Compile" +Bitmap Path1="" +Show DOS Window1=0 +Capture1=1 +Capture Mode1=3 +WinProg1=1 +SaveAllFiles1=1 +Save Active File1=1 +Replace Type1=0 +Tool Cmd2="" +Tool Dir2="" +Tool Menu2="" +Bitmap Path2="" +Show DOS Window2=1 +Capture2=1 +Capture Mode2=0 +WinProg2=0 +SaveAllFiles2=0 +Save Active File2=0 +Replace Type2=0 +Tool Cmd3="" +Tool Dir3="" +Tool Menu3="" +Bitmap Path3="" +Show DOS Window3=1 +Capture3=1 +Capture Mode3=0 +WinProg3=0 +SaveAllFiles3=0 +Save Active File3=0 +Replace Type3=0 +Tool Cmd4="" +Tool Dir4="" +Tool Menu4="" +Bitmap Path4="" +Show DOS Window4=1 +Capture4=1 +Capture Mode4=0 +WinProg4=0 +SaveAllFiles4=0 +Save Active File4=0 +Replace Type4=0 +Tool Cmd5="" +Tool Dir5="" +Tool Menu5="" +Bitmap Path5="" +Show DOS Window5=1 +Capture5=1 +Capture Mode5=0 +WinProg5=0 +SaveAllFiles5=0 +Save Active File5=0 +Replace Type5=0 +Tool Cmd6="" +Tool Dir6="" +Tool Menu6="" +Bitmap Path6="" +Show DOS Window6=1 +Capture6=1 +Capture Mode6=0 +WinProg6=0 +SaveAllFiles6=0 +Save Active File6=0 +Replace Type6=0 +Tool Cmd7="" +Tool Dir7="" +Tool Menu7="" +Bitmap Path7="" +Show DOS Window7=1 +Capture7=1 +Capture Mode7=0 +WinProg7=0 +SaveAllFiles7=0 +Save Active File7=0 +Replace Type7=0 +Tool Cmd8="" +Tool Dir8="" +Tool Menu8="" +Bitmap Path8="" +Show DOS Window8=1 +Capture8=1 +Capture Mode8=0 +WinProg8=0 +SaveAllFiles8=0 +Save Active File8=0 +Replace Type8=0 +Tool Cmd9="" +Tool Dir9="" +Tool Menu9="" +Bitmap Path9="" +Show DOS Window9=1 +Capture9=1 +Capture Mode9=0 +WinProg9=0 +SaveAllFiles9=0 +Save Active File9=0 +Replace Type9=0 +[Open Files] +<<<<<<< .mine +Open File0= +Open File Pos0=35320 +Open File Line0=33547 +Active File Index=0 +Open File Window Pos0=2,3,-1,-1,-4,-30,88,116,844,680 +Open File1= +Active File Display Mode=-1 +Open File Pos1=129 +Open File Line1=0 +Open File Window Pos1=0,1,-1,-1,-4,-30,66,87,688,627 +Open File2=Z:\public_html\dbdesigner\index.php +Open File Pos2=233 +Open File Line2=0 +Open File Window Pos2=0,1,-1,-1,-4,-30,66,87,688,627 +Open File3= +Open File Pos3=903 +Open File Line3=423 +Open File Window Pos3=0,1,-1,-1,-4,-30,88,116,799,666 +Open File4=C:\Documents and Settings\doy\My Documents\UltraEdit\wordfile.txt +Open File Pos4=305 +======= +Open File0= +Open File Pos0=2249 +Open File Line0=0 +Active File Index=1 +Open File Window Pos0=0,1,-1,-1,-4,-30,66,87,684,623 +Open File1=Z:\public_html\xmlsocketd\src\server.cpp +Active File Display Mode=-1 +Open File Pos1=6750 +Open File Line1=6329 +Open File Window Pos1=2,3,-1,-1,-4,-30,88,116,710,656 +Open File2=Z:\public_html\xmlsocketd\src\server.h +Open File Pos2=1235 +Open File Line2=560 +Open File Window Pos2=0,1,-1,-1,-4,-30,132,174,798,604 +Open File3=Z:\public_html\xmlsocketd\src\main.cpp +Open File Pos3=2894 +Open File Line3=1382 +Open File Window Pos3=0,1,-1,-1,-4,-30,154,203,820,633 +Open File4=Z:\public_html\xmlsocketd\src\config.h +Open File Pos4=12 +>>>>>>> .r24 +Open File Line4=0 +Open File Window Pos4=0,1,-1,-1,-4,-30,0,0,666,430 +Open File5=Z:\public_html\xmlsocketd\src\stringqueue.cpp +Open File Pos5=0 +Open File Line5=0 +Open File Window Pos5=0,1,-1,-1,-4,-30,22,29,688,459 +Open File6=Z:\public_html\xmlsocketd\src\user.h +Open File Pos6=1062 +Open File Line6=435 +Open File Window Pos6=0,1,-1,-1,-4,-30,44,58,710,488 +Open File7=Z:\public_html\xmlsocketd\src\message.cpp +Open File Pos7=381 +Open File Line7=97 +Open File Window Pos7=0,1,-1,-1,-4,-30,66,87,732,517 +Open File8=Z:\public_html\xmlsocketd\src\room.cpp +Open File Pos8=3670 +Open File Line8=2689 +Open File Window Pos8=0,1,-1,-1,-4,-30,88,116,754,546 +Open File9=Z:\public_html\xmlsocketd\src\user.cpp +Open File Pos9=8357 +Open File Line9=6352 +Open File Window Pos9=0,1,-1,-1,-4,-30,110,145,776,575 +Open File10= +[Project Information] +Use Relative Directory=1 +Relative to Project File=1 +Project Start=D507030004001F000B001C002800000051 +======= +Filter=*.cpp;*.h;*.as +Include Sub Directories=1 +Project Tagfile=C:\xmlsocketd.ctags +Project Wordfile= +Create Tagfile=1 +Working Time=135061 +>>>>>>> .r24 +[Folders] +C:\Documents and Settings\Administrator\Desktop\xmlsocketd\ - FlashAPI - join=1 +C:\Documents and Settings\Administrator\Desktop\xmlsocketd\ - FlashAPI - XMLSocketd=1 +C:\Documents and Settings\Administrator\Desktop\xmlsocketd\ - src=1 +ActionScript=1 +cpp=1 +headers=1 +ActionScript - Classes=1 +ActionScript - join=1 +[Group] +0=cpp +1=headers +2=ActionScript +3=ActionScript - Classes +4=ActionScript - join +[Files - cpp] +0=src\xmlparser.cpp +1=src\user.cpp +2=src\stringqueue.cpp +3=src\server.cpp +4=src\room.cpp +5=src\message.cpp +6=src\authorizehttpconnection.cpp +7=src\httpconnection.cpp +8=src\main.cpp +[Files - headers] +0=src\xmlparser.h +1=src\user.h +2=src\stringqueue.h +3=src\server_private.h +4=src\server.h +5=src\room.h +6=src\authorizehttpconnection.h +7=src\httpconnection.h +8=src\config.h +9=src\message.h +[Files - ActionScript - Classes] +0=FlashAPI\XMLSocketd\Connection.as +1=FlashAPI\XMLSocketd\Room.as +2=FlashAPI\XMLSocketd\User.as +[Files - ActionScript] +0=FlashAPI\example.as +[Files - ActionScript - join] +0=FlashAPI\join\index.php diff --git a/xmltags.txt b/xmltags.txt new file mode 100755 index 0000000..114dfc0 --- /dev/null +++ b/xmltags.txt @@ -0,0 +1,17 @@ + +Client to Server: + room:join = User tries to join a room + system:setname = User sets nickname on server + message = A room message + +Server to Client: + message = A room message + room:authorized = User gains authorization to a room + room:unauthorized = User denies access to a room + userlist = List of modifications in the rooms userlist + +Server to Webserver: + room:join = User want to join a room + +Webserver to Server: + room:authorized = User is authorized to a room by the webserver.