提交 5142db00c4f1ada28b7155e089bbcf4d099ef57a

作者 LJH 李佳桓
1 个父辈 84728c9f

add

正在显示 1 个修改的文件 包含 352 行增加0 行删除
  1 +/*
  2 + * Copyright 2007 Stephen Liu
  3 + * For license terms, see the file COPYING along with this library.
  4 + */
  5 +
  6 +#include <stdio.h>
  7 +#include <stdlib.h>
  8 +#include <string.h>
  9 +#include <signal.h>
  10 +#include <assert.h>
  11 +
  12 +#include "spthread.hpp"
  13 +
  14 +#include "spmsgdecoder.hpp"
  15 +#include "spbuffer.hpp"
  16 +
  17 +#include "spserver.hpp"
  18 +#include "splfserver.hpp"
  19 +#include "sphandler.hpp"
  20 +#include "spresponse.hpp"
  21 +#include "sprequest.hpp"
  22 +
  23 +#ifdef WIN32
  24 +#include "spgetopt.h"
  25 +#endif
  26 +
  27 +class SP_OnlineSidList {
  28 +public:
  29 + SP_OnlineSidList();
  30 + ~SP_OnlineSidList();
  31 +
  32 + void copy( SP_SidList * outList, SP_Sid_t * ignoreSid = NULL );
  33 + void remove( SP_Sid_t sid );
  34 + void add( SP_Sid_t sid );
  35 + int getCount();
  36 +
  37 +private:
  38 + SP_SidList mList;
  39 + sp_thread_mutex_t mMutex;
  40 +};
  41 +
  42 +SP_OnlineSidList :: SP_OnlineSidList()
  43 +{
  44 + sp_thread_mutex_init( &mMutex, NULL );
  45 +}
  46 +
  47 +SP_OnlineSidList :: ~SP_OnlineSidList()
  48 +{
  49 + sp_thread_mutex_destroy( &mMutex );
  50 +}
  51 +
  52 +void SP_OnlineSidList :: copy( SP_SidList * outList, SP_Sid_t * ignoreSid )
  53 +{
  54 + sp_thread_mutex_lock( &mMutex );
  55 +
  56 + for( int i = 0; i < mList.getCount(); i++ ) {
  57 + if( NULL != ignoreSid ) {
  58 + SP_Sid_t theSid = mList.get( i );
  59 + if( theSid.mKey == ignoreSid->mKey && theSid.mSeq == ignoreSid->mSeq ) {
  60 + continue;
  61 + }
  62 + }
  63 +
  64 + outList->add( mList.get( i ) );
  65 + }
  66 +
  67 + sp_thread_mutex_unlock( &mMutex );
  68 +}
  69 +
  70 +void SP_OnlineSidList :: remove( SP_Sid_t sid )
  71 +{
  72 + sp_thread_mutex_lock( &mMutex );
  73 +
  74 + for( int i = 0; i < mList.getCount(); i++ ) {
  75 + SP_Sid_t theSid = mList.get( i );
  76 + if( theSid.mKey == sid.mKey && theSid.mSeq == sid.mSeq ) {
  77 + mList.take( i );
  78 + break;
  79 + }
  80 + }
  81 +
  82 + sp_thread_mutex_unlock( &mMutex );
  83 +}
  84 +
  85 +void SP_OnlineSidList :: add( SP_Sid_t sid )
  86 +{
  87 + sp_thread_mutex_lock( &mMutex );
  88 +
  89 + mList.add( sid );
  90 +
  91 + sp_thread_mutex_unlock( &mMutex );
  92 +}
  93 +
  94 +int SP_OnlineSidList :: getCount()
  95 +{
  96 + int count = 0;
  97 +
  98 + sp_thread_mutex_lock( &mMutex );
  99 +
  100 + count = mList.getCount();
  101 +
  102 + sp_thread_mutex_unlock( &mMutex );
  103 +
  104 + return count;
  105 +}
  106 +
  107 +//---------------------------------------------------------
  108 +
  109 +class SP_ChatHandler : public SP_Handler {
  110 +public:
  111 + SP_ChatHandler( SP_OnlineSidList * onlineSidList );
  112 + virtual ~SP_ChatHandler();
  113 +
  114 + virtual int start( SP_Request * request, SP_Response * response );
  115 +
  116 + // return -1 : terminate session, 0 : continue
  117 + virtual int handle( SP_Request * request, SP_Response * response );
  118 +
  119 + virtual void error( SP_Response * response );
  120 +
  121 + virtual void timeout( SP_Response * response );
  122 +
  123 + virtual void close();
  124 +
  125 +private:
  126 + SP_Sid_t mSid;
  127 +
  128 + SP_OnlineSidList * mOnlineSidList;
  129 +
  130 + static int mMsgSeq;
  131 +
  132 + void broadcast( SP_Response * response, const char * buffer, SP_Sid_t * ignoreSid = 0 );
  133 +};
  134 +
  135 +int SP_ChatHandler :: mMsgSeq = 0;
  136 +
  137 +SP_ChatHandler :: SP_ChatHandler( SP_OnlineSidList * onlineSidList )
  138 +{
  139 + memset( &mSid, 0, sizeof( mSid ) );
  140 +
  141 + mOnlineSidList = onlineSidList;
  142 +}
  143 +
  144 +SP_ChatHandler :: ~SP_ChatHandler()
  145 +{
  146 +}
  147 +
  148 +void SP_ChatHandler :: broadcast( SP_Response * response, const char * buffer, SP_Sid_t * ignoreSid )
  149 +{
  150 + if( mOnlineSidList->getCount() > 0 ) {
  151 + SP_Message * msg = new SP_Message();
  152 + mOnlineSidList->copy( msg->getToList(), ignoreSid );
  153 + msg->setCompletionKey( ++mMsgSeq );
  154 +
  155 + msg->getMsg()->append( buffer );
  156 + response->addMessage( msg );
  157 + }
  158 +}
  159 +
  160 +int SP_ChatHandler :: start( SP_Request * request, SP_Response * response )
  161 +{
  162 + request->setMsgDecoder( new SP_LineMsgDecoder() );
  163 +
  164 + mSid = response->getFromSid();
  165 +
  166 + char buffer[ 128 ] = { 0 };
  167 + snprintf( buffer, sizeof( buffer ),
  168 + "Welcome %d to chat server, enter 'quit' to quit.\r\n", mSid.mKey );
  169 + response->getReply()->getMsg()->append( buffer );
  170 + response->getReply()->setCompletionKey( ++mMsgSeq );
  171 +
  172 + snprintf( buffer, sizeof( buffer ), "SYS : %d online\r\n", mSid.mKey);
  173 +
  174 + broadcast( response, buffer );
  175 +
  176 + mOnlineSidList->add( mSid );
  177 +
  178 + return 0;
  179 +}
  180 +
  181 +int SP_ChatHandler :: handle( SP_Request * request, SP_Response * response )
  182 +{
  183 + SP_LineMsgDecoder * decoder = (SP_LineMsgDecoder*)request->getMsgDecoder();
  184 +
  185 + char buffer[ 256 ] = { 0 };
  186 +
  187 + if( 0 != strcasecmp( (char*)decoder->getMsg(), "quit" ) ) {
  188 + snprintf( buffer, sizeof( buffer ), "%d say: %s\r\n", mSid.mKey, (char*)decoder->getMsg() );
  189 + broadcast( response, buffer );
  190 +
  191 + return 0;
  192 + } else {
  193 + snprintf( buffer, sizeof( buffer ), "SYS : %d normal offline\r\n", mSid.mKey );
  194 + broadcast( response, buffer, &mSid );
  195 +
  196 + response->getReply()->getMsg()->append( "SYS : Byebye\r\n" );
  197 + response->getReply()->setCompletionKey( ++mMsgSeq );
  198 +
  199 + return -1;
  200 + }
  201 +}
  202 +
  203 +void SP_ChatHandler :: error( SP_Response * response )
  204 +{
  205 + char buffer[ 64 ] = { 0 };
  206 + snprintf( buffer, sizeof( buffer ), "SYS : %d error offline\r\n", mSid.mKey );
  207 +
  208 + broadcast( response, buffer, &mSid );
  209 +}
  210 +
  211 +void SP_ChatHandler :: timeout( SP_Response * response )
  212 +{
  213 + char buffer[ 64 ] = { 0 };
  214 + snprintf( buffer, sizeof( buffer ), "SYS : %d timeout offline\r\n", mSid.mKey );
  215 +
  216 + broadcast( response, buffer, &mSid );
  217 +}
  218 +
  219 +void SP_ChatHandler :: close()
  220 +{
  221 + mOnlineSidList->remove( mSid );
  222 +}
  223 +
  224 +//---------------------------------------------------------
  225 +
  226 +class SP_ChatCompletionHandler : public SP_CompletionHandler {
  227 +public:
  228 + SP_ChatCompletionHandler();
  229 + ~SP_ChatCompletionHandler();
  230 + virtual void completionMessage( SP_Message * msg );
  231 +};
  232 +
  233 +SP_ChatCompletionHandler :: SP_ChatCompletionHandler()
  234 +{
  235 +}
  236 +
  237 +SP_ChatCompletionHandler :: ~SP_ChatCompletionHandler()
  238 +{
  239 +}
  240 +
  241 +void SP_ChatCompletionHandler :: completionMessage( SP_Message * msg )
  242 +{
  243 +#if 0
  244 + printf( "message completed { completion key : %d }\n", msg->getCompletionKey() );
  245 +
  246 + printf( "\tsuccess {" );
  247 + for( int i = 0; i < msg->getSuccess()->getCount(); i++ ) {
  248 + printf( " %d", msg->getSuccess()->get( i ).mKey );
  249 + }
  250 + printf( "}\n" );
  251 +
  252 + printf( "\tfailure {" );
  253 + for( int i = 0; i < msg->getFailure()->getCount(); i++ ) {
  254 + printf( " %d", msg->getFailure()->get( i ).mKey );
  255 + }
  256 + printf( "}\n" );
  257 +#endif
  258 +
  259 + delete msg;
  260 +}
  261 +
  262 +//---------------------------------------------------------
  263 +
  264 +class SP_ChatHandlerFactory : public SP_HandlerFactory {
  265 +public:
  266 + SP_ChatHandlerFactory( SP_OnlineSidList * onlineSidList );
  267 + virtual ~SP_ChatHandlerFactory();
  268 +
  269 + virtual SP_Handler * create() const;
  270 +
  271 + virtual SP_CompletionHandler * createCompletionHandler() const;
  272 +
  273 +private:
  274 + SP_OnlineSidList * mOnlineSidList;
  275 +};
  276 +
  277 +SP_ChatHandlerFactory :: SP_ChatHandlerFactory( SP_OnlineSidList * onlineSidList )
  278 +{
  279 + mOnlineSidList = onlineSidList;
  280 +}
  281 +
  282 +SP_ChatHandlerFactory :: ~SP_ChatHandlerFactory()
  283 +{
  284 +}
  285 +
  286 +SP_Handler * SP_ChatHandlerFactory :: create() const
  287 +{
  288 + return new SP_ChatHandler( mOnlineSidList );
  289 +}
  290 +
  291 +SP_CompletionHandler * SP_ChatHandlerFactory :: createCompletionHandler() const
  292 +{
  293 + return new SP_ChatCompletionHandler();
  294 +}
  295 +
  296 +//---------------------------------------------------------
  297 +
  298 +int main( int argc, char * argv[] )
  299 +{
  300 + int port = 5555, maxThreads = 10;
  301 + const char * serverType = "hahs";
  302 +
  303 + extern char *optarg ;
  304 + int c ;
  305 +
  306 + while( ( c = getopt ( argc, argv, "p:t:s:v" )) != EOF ) {
  307 + switch ( c ) {
  308 + case 'p' :
  309 + port = atoi( optarg );
  310 + break;
  311 + case 't':
  312 + maxThreads = atoi( optarg );
  313 + break;
  314 + case 's':
  315 + serverType = optarg;
  316 + break;
  317 + case '?' :
  318 + case 'v' :
  319 + printf( "Usage: %s [-p <port>] [-t <threads>] [-s <hahs|lf>]\n", argv[0] );
  320 + exit( 0 );
  321 + }
  322 + }
  323 +
  324 + sp_openlog( "testchat", LOG_CONS | LOG_PID | LOG_PERROR, LOG_USER );
  325 +
  326 + assert( 0 == sp_initsock() );
  327 +
  328 + SP_OnlineSidList onlineSidList;
  329 +
  330 + if( 0 == strcasecmp( serverType, "hahs" ) ) {
  331 + SP_Server server( "", port, new SP_ChatHandlerFactory( &onlineSidList ) );
  332 +
  333 + server.setTimeout( 60 );
  334 + server.setMaxThreads( maxThreads );
  335 + server.setReqQueueSize( 100, "Sorry, server is busy now!\n" );
  336 +
  337 + server.runForever();
  338 + } else {
  339 + SP_LFServer server( "", port, new SP_ChatHandlerFactory( &onlineSidList ) );
  340 +
  341 + server.setTimeout( 60 );
  342 + server.setMaxThreads( maxThreads );
  343 + server.setReqQueueSize( 100, "Sorry, server is busy now!\n" );
  344 +
  345 + server.runForever();
  346 + }
  347 +
  348 + sp_closelog();
  349 +
  350 + return 0;
  351 +}
  352 +
... ...
注册登录 后发表评论