isolationserver/isoserver/src/isoservermain.c
changeset 10 59927b2d3b75
parent 0 d0f3a028347a
equal deleted inserted replaced
0:d0f3a028347a 10:59927b2d3b75
     1 /*
       
     2 * ============================================================================
       
     3 *  Name        : isoservermain.c
       
     4 *  Part of     : isolation server.
       
     5 *  Version     : %version: 33 %
       
     6 *
       
     7 *  Copyright © 2007-2008 Nokia.  All rights reserved.
       
     8 *  All rights reserved.
       
     9 *  Redistribution and use in source and binary forms, with or without modification, 
       
    10 *  are permitted provided that the following conditions are met:
       
    11 *  Redistributions of source code must retain the above copyright notice, this list 
       
    12 *  of conditions and the following disclaimer.Redistributions in binary form must 
       
    13 *  reproduce the above copyright notice, this list of conditions and the following 
       
    14 *  disclaimer in the documentation and/or other materials provided with the distribution.
       
    15 *  Neither the name of the Nokia Corporation nor the names of its contributors may be used 
       
    16 *  to endorse or promote products derived from this software without specific prior written 
       
    17 *  permission.
       
    18 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
       
    19 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
       
    20 *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
       
    21 *  SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
       
    22 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
       
    23 *  OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
       
    24 *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
       
    25 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
       
    26 *  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    27 * ============================================================================
       
    28 * Template version: 1.0
       
    29 */
       
    30 
       
    31 
       
    32 #include <glib.h>
       
    33 
       
    34 #include <gtypes.h>
       
    35 #include <sys/types.h>   
       
    36 #include <stdlib.h>
       
    37 #include <string.h>
       
    38 
       
    39 #include <netinet/in.h>
       
    40 #include <stdio.h>  
       
    41 #include <netdb.h>
       
    42 #include <unistd.h>
       
    43 #include <errno.h>
       
    44 #include "msgqlib.h"
       
    45 #include "msg_enums.h"
       
    46 #include "msgliterals.h"
       
    47 #include "isoservermain.h"
       
    48 #include "isoim.h"
       
    49 #include "isoconnectionmanager.h"
       
    50 #include "isomodifycontactlist.h"
       
    51 #include "isoutils.h"
       
    52 #include "isopresence.h"
       
    53 #include "isoutils.h"
       
    54 #include "isoavtar.h"
       
    55 #include "isosearch.h"
       
    56 #include "isogetsearchkeys.h"
       
    57 #include "isofetchcontactlist.h"
       
    58 
       
    59 /*!	\file 
       
    60 *	Impliments the functions in isoservermain.h
       
    61 */
       
    62 
       
    63 /*!	\def Thread stack size
       
    64 */
       
    65 #define THREAD_STACK_SIZE	26000
       
    66 
       
    67 /*! \var mainloop_struct global variable having a pointer to mainloop
       
    68 */
       
    69 globalMainloop mainloop_struct;
       
    70 
       
    71 /*!	\var globalCon one object per login session
       
    72 */
       
    73 userConnection globalCon;
       
    74 
       
    75 
       
    76 /*! /brief This message reads message type from the message buffer
       
    77 *   passed as argument
       
    78 *
       
    79 *   /var pc message buffer
       
    80 *   
       
    81 *   /return pointer to message header response which has the message type
       
    82 */
       
    83 message_hdr_resp* read_message_type( gchar* buf ) 
       
    84 	{
       
    85 	
       
    86 	message_hdr_resp *msg_hdr = NULL;
       
    87 	iso_logger( "%s", "In - read_message_type\n" );
       
    88 	//allocate memory and check for error
       
    89 	msg_hdr = ( message_hdr_resp* ) malloc( sizeof( message_hdr_resp ) );
       
    90 	if ( NULL == msg_hdr ) 
       
    91 		{
       
    92 		return NULL;	
       
    93 		}
       
    94 	//initialze memory to 0
       
    95     memset( msg_hdr, '\0', sizeof( message_hdr_resp ) );
       
    96     //read message request header from buffer
       
    97     memcpy( msg_hdr, buf, sizeof( message_hdr_req ) );
       
    98     iso_logger( "%s", "Out - read_message_type\n" );
       
    99     //return message header read from buffer
       
   100 	return msg_hdr;
       
   101 	}
       
   102 
       
   103 /*! /brief This is an entry point to the thread. isoserver.exe
       
   104 *   creates a thread which runs a mainloop. mainloop is passed as 
       
   105 *   argument to the thread entry function. This mainloop which is 
       
   106 *   run in the thread listens for the events from telepathygabble
       
   107 *
       
   108 *   /var data unused param
       
   109 */
       
   110 gpointer thread_entry( gpointer data ) 
       
   111 	{
       
   112 	UNUSED_FORMAL_PARAM(data);
       
   113 	//wait till status_changed_cb to happen
       
   114 	//The only main loop is run in a thread..
       
   115 	iso_logger( "%s", "In - thread_entry\n" );
       
   116 	//run the mainloop in thread..
       
   117 	g_main_loop_run( mainloop_struct.mainloop ); 
       
   118 	iso_logger( "%s", "Out - thread_entry\n" );
       
   119 	return NULL;
       
   120 	}
       
   121 	
       
   122 /*! /brief If there are any parse error, this function is called to
       
   123 *   dispatch the error to client.
       
   124 *   
       
   125 *   /param msg_struct The response header to be sent 
       
   126 *   /param err Error
       
   127 */
       
   128 gint send_error( message_hdr_resp* msg_struct, gint err )	
       
   129 	{
       
   130 	int result = 0;
       
   131 	int pri = MSG_PRI_NORMAL;
       
   132 	int timeout = NO_WAIT; 
       
   133 	int error = 0;  
       
   134 	
       
   135 	//set the error and reason
       
   136 	msg_struct->error_type = err;
       
   137 	//Since this is method to send error
       
   138 	//response is always 0
       
   139 	msg_struct->response = 0;
       
   140 	
       
   141 	//request has fialed send appr. response
       
   142 	result = MsgQCreate( RESPONSE_QUEUE, MAX_MSG_Q_SIZE, MSG_Q_FIFO, &error );
       
   143 	if ( ERROR == result )
       
   144 		{
       
   145 		//graceful exit?
       
   146 		return ERROR;
       
   147 		}
       
   148 		
       
   149 	//send message created to client		
       
   150 	result = MsgQSend( RESPONSE_QUEUE, (void*)msg_struct, sizeof( message_hdr_resp ),
       
   151 			 pri, timeout, &error );
       
   152 			
       
   153 	if( result != 0 )
       
   154 		{
       
   155 		// msg deliver falied 
       
   156 		return MSG_Q_SEND_FAILED;
       
   157 		}
       
   158 	return 0;	
       
   159 	}
       
   160 	
       
   161 /*! /brief This function waits for the requests from the client.
       
   162 *   Requests are parsed, validated and appropriate actions taken.
       
   163 *   A new thread is created when login happens. This function runs 
       
   164 *   a while loop which is only quit when a kill request is recieved 
       
   165 *   from the client.
       
   166 *
       
   167 *   /remark should this thread be created before login?
       
   168 *   /remark when is the mainloop quit ? (Should that be after logout or 
       
   169 *   after getting a kill request from the client)
       
   170 */
       
   171 int message_send_recv() 
       
   172 	{
       
   173     
       
   174 	int err = 0;
       
   175 	int result = 0;
       
   176 	int timeout1 = TIME_OUT; // block for 100 ms
       
   177 	char rmsg[MAX_MSG_SIZE];  // 1024 bytes
       
   178 	GMainLoop* mainloop = NULL;
       
   179 	GThread* join1 = NULL;
       
   180 	message_hdr_resp* msg_struct = NULL;
       
   181 	GArray* avtarcontent = NULL;
       
   182 	
       
   183 	globalCon.conn_stat = disconnected;
       
   184 	globalCon.logout_flag = 0;
       
   185 
       
   186 	/* Try to Create queueOne again, this will create the queue again,
       
   187 	   this will just return as its already created by main thread */
       
   188 	iso_logger( "%s", "In - message_send_recv\n" );
       
   189 	
       
   190 	result = MsgQCreate(REQUEST_QUEUE, MAX_MSG_Q_SIZE, MSG_Q_FIFO, &err);
       
   191 	
       
   192 	//logic here to accept multiple clients
       
   193 	mainloop = g_main_loop_new ( NULL, FALSE ); //global mainloop
       
   194 	
       
   195 	
       
   196 	if ( ERROR == result || NULL == mainloop )
       
   197 		{
       
   198 		return ERROR;
       
   199 		}
       
   200 	
       
   201 	mainloop_struct.mainloop = mainloop;
       
   202 
       
   203 	while( 1 ) 
       
   204 		{
       
   205 			
       
   206 		//initalize memory to 0
       
   207 		memset( rmsg, '\0', MAX_MSG_SIZE );
       
   208 		// Receive Message from queueTwo 
       
   209 		result = MsgQReceive(REQUEST_QUEUE, rmsg, MAX_MSG_SIZE, timeout1, &err); 
       
   210 		
       
   211 		//MRT bug - 4 more bytes recieved than sent..
       
   212 		result -= 4; 
       
   213 
       
   214 
       
   215 		//The message should be atleast of size msg_hdr_req
       
   216 		//sizeof should be type casted to gint 
       
   217 		//coz when comparing gint and guint(sizeof return value) 
       
   218 		//gint is converted to guint
       
   219 		if( result >= ( gint )sizeof( message_hdr_req ) )
       
   220 			{
       
   221 			gboolean stat_err = FALSE;
       
   222 			// read message header and get type..
       
   223 			msg_struct = read_message_type( rmsg );
       
   224 			if ( NULL == msg_struct ) 
       
   225 				{
       
   226 				//needs to be discussed what can be done..
       
   227 				//should exit from here?
       
   228 				return MEM_ALLOCATION_ERROR;	
       
   229 				}
       
   230 			switch( globalCon.conn_stat )
       
   231 			    {
       
   232 			    case connected:
       
   233 			        {
       
   234 			            //switch to the message type, where action to be performed
       
   235 			            //is decided dpending on the message type
       
   236 			            switch ( msg_struct->hdr_req.message_type ) 
       
   237 			            {
       
   238                             
       
   239                         case ESend_Request:
       
   240                             {
       
   241                             iso_logger( "%s", "In - ESend_Request\n" );
       
   242                             //parse the request and 
       
   243                             // send the request to telepathy
       
   244                             err = action_parse_send( rmsg, result );
       
   245                             if ( err < 0 ) 
       
   246                                 {
       
   247                                 //Send request has failed..
       
   248                                 //send the error code to the client
       
   249                                 send_error( msg_struct, err );
       
   250                                 }
       
   251                         
       
   252                             break;
       
   253                             }
       
   254                         case EUpdateOwnPresence:
       
   255                             {
       
   256                             iso_logger( "%s", "In - EUpdateOwnPresence\n" );
       
   257                             //parse the request and 
       
   258                             // send the request to telepathy
       
   259                             err = action_parse_presence( rmsg, result );
       
   260                             if ( err < 0 ) 
       
   261                                 {
       
   262                                 //Send request has failed..
       
   263                                 //send the error code to the client
       
   264                                 send_error( msg_struct, err );
       
   265                                 }
       
   266                         
       
   267                             break;
       
   268                             } 
       
   269                         //For accept, add and delete same function does the job
       
   270                         //depending on the message type that is passed with rmsg
       
   271                         case EReject_Contact_Request:
       
   272                         
       
   273                         case EAccept_Contact_Request:
       
   274                         
       
   275                         case EAdd_Contact_Request:
       
   276                         
       
   277                         case EDelete_Contact_Request:
       
   278                             {
       
   279                             iso_logger( "%s", "In - modify Contact \n" );
       
   280                             //Parse the request for to add contact and 
       
   281                             //request telepathy to add contact
       
   282                             err = action_parse_modify_contact_list( rmsg, result );
       
   283                             if ( err < 0 ) 
       
   284                                 {
       
   285                                 //addcontacts has fialed send appr. response
       
   286                                 send_error( msg_struct, err );
       
   287                                 }
       
   288                         
       
   289                             break;
       
   290                             }
       
   291                         
       
   292                         case ESearch:
       
   293                             {
       
   294                             iso_logger( "%s", "In - ESearch\n" );
       
   295                             //parse the request and 
       
   296                             // send the request to telepathy
       
   297                             err = action_parse_search( rmsg, result );
       
   298                             if ( err < 0 ) 
       
   299                                 {
       
   300                                 //Send request has failed..
       
   301                                 //send the error code to the client
       
   302                                 iso_logger( "%s %d", "error in - ESearch error code:", err );
       
   303                                 send_error( msg_struct, err );
       
   304                                 }
       
   305                             break;                      
       
   306                             }
       
   307                             
       
   308                         case ESearch_Get_Keys:
       
   309                             {
       
   310                             iso_logger( "%s", "In - ESearch_Get_Keys\n" );
       
   311                             err = get_search_keys( msg_struct );
       
   312                             
       
   313                             if ( err < 0 ) 
       
   314                                 {
       
   315                                 //Send request has failed..
       
   316                                 //send the error code to the client
       
   317                                 iso_logger( "%s %d", "error in - ESearch_Get_Keys error code:", err );
       
   318                                 send_error( msg_struct, err );
       
   319                                 }
       
   320                                 
       
   321                             break;
       
   322                             }
       
   323                         case ELogout_Request:
       
   324                             {
       
   325                             //Message type is to logout
       
   326                             iso_logger( "%s", "In - logout\n" );
       
   327                             globalCon.conn_stat = disconnecting;
       
   328                             action_logout( rmsg );
       
   329                             //globalCon.logout_flag = 1;
       
   330                             break;  
       
   331                             }
       
   332                         case EUpdateOwnAvtar:
       
   333                            {
       
   334                            err = update_own_avatar( rmsg,msg_struct,result, &avtarcontent);
       
   335                            if ( err < 0 ) 
       
   336                                {
       
   337                                //Send request has failed..
       
   338                                //send the error code to the client
       
   339                                iso_logger( "%s %d", "error in - ESearch_Get_Keys error code:", err );
       
   340                                send_error( msg_struct, err );
       
   341                                }                     
       
   342                            break;
       
   343                            }
       
   344                         case EClearOwnAvatar:
       
   345                             {
       
   346                             err = clear_avatar( &(msg_struct->hdr_req) );
       
   347                             if ( err < 0 ) 
       
   348                                {
       
   349                                //Send request has failed..
       
   350                                //send the error code to the client
       
   351                                send_error( msg_struct, err );
       
   352                                }
       
   353                             break;
       
   354                             }
       
   355                         case EFetchCachedContacts:
       
   356                             fetch_cached_contacts();
       
   357                             break;
       
   358                             
       
   359                         default:
       
   360                             {
       
   361                             iso_logger( "%s", "In - default state is connected\n" );
       
   362                             stat_err = TRUE;
       
   363                             break;  
       
   364                             }
       
   365                         
       
   366                          }
       
   367 			        }
       
   368 			        break;
       
   369 			    case disconnected:
       
   370 			        switch( msg_struct->hdr_req.message_type )
       
   371                     {
       
   372                     case ELogin_Request:
       
   373                         {
       
   374                         //parse the message buffer and login
       
   375                         iso_logger( "%s", "In - login\n" );
       
   376                         //parses the request message and does a login 
       
   377                         //if all the parameters are correct
       
   378                         globalCon.conn_stat = connecting;
       
   379                         err = action_parse_login( rmsg, result );
       
   380                         //If there is no error in login create a new thread
       
   381                         //where mainloop will be run..
       
   382                         if ( !err )  
       
   383                             {
       
   384                             //Create a thread for the mainloop to run..
       
   385                             //Thread entry does a run on mainloop
       
   386                             join1 = g_thread_create_full( thread_entry, mainloop, 
       
   387                                     THREAD_STACK_SIZE, TRUE, FALSE,
       
   388                                     G_THREAD_PRIORITY_NORMAL , NULL );  
       
   389                         
       
   390                             
       
   391                             }
       
   392                         else 
       
   393                             {
       
   394                             //There was some error while loging in.. send the error 
       
   395                             //to client
       
   396                             globalCon.conn_stat = disconnected;
       
   397                             send_error( msg_struct, err );
       
   398                             }
       
   399                         break;
       
   400                         }
       
   401                         
       
   402                     default:
       
   403                         {
       
   404                         iso_logger( "%s", "In - default state is disconnected\n" );
       
   405                         stat_err = TRUE;
       
   406                         }
       
   407                     }
       
   408 			        break;
       
   409 			    case not_connected:
       
   410 			        switch( msg_struct->hdr_req.message_type )
       
   411 			            {
       
   412 			            case  EKill_Process :
       
   413                             {
       
   414                             //no need to change the state as anyways it is going to be killed
       
   415                             //globalCon.conn_stat = not_connected;
       
   416                             globalCon.logout_flag = 1;
       
   417                             break;
       
   418                             }
       
   419 			            default:
       
   420                             {
       
   421                             iso_logger( "%s", "In - default state is not_connected\n" );
       
   422                             stat_err = TRUE;
       
   423                             }
       
   424 			            }
       
   425 			        break;
       
   426 			    default:
       
   427 			        {
       
   428 			        iso_logger( "%s", "In - default state connecting or disconnecting \n" );
       
   429                     stat_err = TRUE;
       
   430                     break;  
       
   431                     }
       
   432 			    }
       
   433 			if ( stat_err )
       
   434 			    {
       
   435 			    stat_err = FALSE;
       
   436 			    iso_logger( "%s", "In - stat_err true \n" );
       
   437 			    send_error( msg_struct, CONNECTION_STATUS_ERROR );
       
   438 			    }
       
   439 			if ( globalCon.logout_flag ) 
       
   440 				{
       
   441 				//quit mainloop before exiting the thread and then server
       
   442 				//quiting mainloop will inturn make the thread to fall off
       
   443 				g_main_loop_quit( mainloop_struct.mainloop );
       
   444 				iso_logger( "%s", "logout flag break \n" );
       
   445 				break;					
       
   446 				}
       
   447 			free ( msg_struct );
       
   448 
       
   449 			}
       
   450 		else 
       
   451 			{
       
   452 			break;			
       
   453 			}
       
   454 		}
       
   455 	iso_logger( "%s", "In - g_thread_join\n" );
       
   456 	
       
   457 	
       
   458 
       
   459 	//join the thread created for to run mainloop before exiting
       
   460 	g_thread_join( join1 );	
       
   461 	iso_logger( "%s", "After this should be after mainloop quit - g_thread_join\n" );
       
   462 	
       
   463 	/* delete message queueOne */
       
   464 	result=MsgQDelete( REQUEST_QUEUE, &err );
       
   465 	
       
   466 	iso_logger( "%s", "Out - MsgQDelete\n" );
       
   467 	return 0;
       
   468 	}
       
   469 
       
   470 /*! \brief server main process which listens to requests from client
       
   471 *	and processes those requests. A new thread is created to listen to
       
   472 *	the events from the telepathygabble. 
       
   473 */
       
   474 int main()
       
   475 	{
       
   476 	int err = 0;
       
   477 	//FILE *fp = NULL;
       
   478 	    
       
   479 	g_type_init();
       
   480 	
       
   481 	g_thread_init( NULL );/*
       
   482 	_dbus_setenv("DBUS_VERBOSE","1");
       
   483 	fp= freopen("c:\\iso-dbus.txt", "a",stderr);*/
       
   484 	iso_logger( "%s", "In - main\n" );
       
   485 	//wait in a loop to accept requests from the client
       
   486 	//Can mainloop be used instead of waiting in a loop?
       
   487 	err = message_send_recv();
       
   488 	if ( err != 0 ) 
       
   489 		{
       
   490 		printf("exit err code is %d\n", err );	
       
   491 		}
       
   492 	iso_logger( "%s", "Out - main\n" );
       
   493 	
       
   494 	//fclose(fp);
       
   495 	return 0;
       
   496 	}