testexecmgmt/ucc/Source/PppdGateway/pppdgateway.c
changeset 0 3da2a79470a7
equal deleted inserted replaced
-1:000000000000 0:3da2a79470a7
       
     1 /*
       
     2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 * Switches
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 //#define SYSTEM_TEST_MP5
       
    22 
       
    23 
       
    24 /*******************************************************************************
       
    25  *
       
    26  * System Includes
       
    27  *
       
    28  ******************************************************************************/
       
    29 #include <stdio.h>
       
    30 #include <stdlib.h>
       
    31 #include <pthread.h>
       
    32 #include <unistd.h>
       
    33 #include <assert.h>
       
    34 #include <errno.h>
       
    35 #include <sys/types.h>
       
    36 #include <sys/socket.h>
       
    37 #include <netinet/in.h>
       
    38 #include <signal.h>
       
    39 #include <string.h>
       
    40 
       
    41 /*******************************************************************************
       
    42  *
       
    43  * Local Includes
       
    44  *
       
    45  ******************************************************************************/
       
    46 #include "socket_helper.h"
       
    47 
       
    48 
       
    49 /*******************************************************************************
       
    50  *
       
    51  * Definitions
       
    52  *
       
    53  ******************************************************************************/
       
    54 #define RECVBUFFSIZE      (4096*4)
       
    55 #define MAXIDSTR          64
       
    56 
       
    57 
       
    58 /*******************************************************************************
       
    59  *
       
    60  * Prototypes
       
    61  *
       
    62  ******************************************************************************/
       
    63 void *receive_ppp_frames( void *x );
       
    64 void *send_ppp_frames( void * );
       
    65 void closesocket( int sockfd );
       
    66 int do_client_server_protocol( int aMobsterDeviceID );
       
    67 
       
    68 
       
    69 /*******************************************************************************
       
    70  *
       
    71  * File-scope
       
    72  *
       
    73  ******************************************************************************/
       
    74 int sockfd;
       
    75 
       
    76 
       
    77 /*******************************************************************************
       
    78  *
       
    79  * Signal Handler
       
    80  *
       
    81  ******************************************************************************/
       
    82 void sigterm( int signum )
       
    83 {
       
    84   pid_t mp = getpid();
       
    85   fprintf( stderr, "PG: pppdgateway(%d) received a SIGTERM -- ignoring\n", mp );
       
    86 }
       
    87 
       
    88 
       
    89 /*******************************************************************************
       
    90  *
       
    91  * Main()
       
    92  *
       
    93  ******************************************************************************/
       
    94 int main( int argc, char *argv[] )
       
    95 {
       
    96   int err;
       
    97   int mobster_device_id = 0;
       
    98   pthread_t threadhandle_send, threadhandle_recv;
       
    99   struct sockaddr_in mobster_addr;
       
   100   __sighandler_t oh;
       
   101 
       
   102   // check args
       
   103   if( argc != 4 ) {
       
   104     fprintf( stderr, "usage: %s mobster_address mobster_port mobster_device_id\n", argv[0] );
       
   105     return -1;
       
   106   }
       
   107   mobster_device_id = atoi(argv[3]);
       
   108   fprintf( stderr, "PG: pppdgateway starting\n" );
       
   109 
       
   110   // setup the signal handler -- note that we ignore SIGTERM! This is because if we shutdown on a SIGTERM we don't
       
   111   // output the TERMREQ -- or receive the TERMACK. Therefore, we rely on the fact that when pppd wants to stop
       
   112   // it will close stdin -- this will cause the output thread to stop -- it will also close the socket which
       
   113   // will cause the input thread to stop -- then the main thread will exit
       
   114   oh = signal( SIGTERM, sigterm );
       
   115   if( oh == SIG_ERR ) {
       
   116     fprintf( stderr, "PG: error registering signal handler (SIGTERM)\n" );
       
   117     return -1;
       
   118   }
       
   119   oh = signal( SIGHUP, sigterm );
       
   120   if( oh == SIG_ERR ) {
       
   121     fprintf( stderr, "PG: error registering signal handler (SIGHUP)\n" );
       
   122     return -1;
       
   123   }
       
   124 
       
   125   // create a TCP socket
       
   126   sockfd = socket( AF_INET, SOCK_STREAM, 0 );
       
   127   if( sockfd == -1 ) {
       
   128     fprintf( stderr, "PG: failed to create socket, exiting.\n" );
       
   129     return -1;
       
   130   }
       
   131 
       
   132   // create the address
       
   133   mobster_addr = getsockaddr( argv[1], argv[2] );
       
   134   if( mobster_addr.sin_addr.s_addr == 0 ) {
       
   135     fprintf( stderr, "PG: invalid address (zero or couldn't resolve hostname), exiting.\n" );
       
   136     closesocket( sockfd );
       
   137     return -1;
       
   138   }
       
   139 
       
   140   // connect to mobster
       
   141   err = connect( sockfd, (struct sockaddr*)&mobster_addr, sizeof(mobster_addr) );
       
   142   if( err != 0 ) {
       
   143     perror( "PG: connect() to server failed\n" );
       
   144     closesocket( sockfd );
       
   145     return -1;
       
   146   }
       
   147 
       
   148   // do the client server protocol - if there is an error the exit
       
   149   err = do_client_server_protocol( mobster_device_id );
       
   150   if( err != 0 ) {
       
   151     fprintf( stderr, "PG: client/server protocol failed.\n" );
       
   152     closesocket( sockfd );
       
   153     return -1;
       
   154   }
       
   155     
       
   156   // change the streams to unbuffered so that this exe doesn't add latency
       
   157   err = setvbuf( stdout, NULL, _IONBF, 0 );
       
   158   if( err != 0 ) {
       
   159     fprintf( stderr, "PG: failed to set buffering on stdout (%d)\n", err );
       
   160     closesocket( sockfd );
       
   161     return -1;
       
   162   }
       
   163   err = setvbuf( stdin, NULL, _IONBF, 0 );
       
   164   if( err != 0 ) {
       
   165     fprintf( stderr, "PG: failed to set buffering on stdout (%d)\n", err );
       
   166     closesocket( sockfd );
       
   167     return -1;
       
   168   }
       
   169   err = setvbuf( stderr, NULL, _IONBF, 0 );
       
   170   if( err != 0 ) {
       
   171     fprintf( stderr, "PG: failed to set buffering on stdout (%d)\n", err );
       
   172     closesocket( sockfd );
       
   173     return -1;
       
   174   }
       
   175 
       
   176   // all the setup is done -- create the threads and let them do their stuff
       
   177   err = pthread_create( &threadhandle_send, NULL, send_ppp_frames, 0 );
       
   178   assert( err == 0 );
       
   179   err = pthread_create( &threadhandle_recv, NULL, receive_ppp_frames, 0 );
       
   180   assert( err == 0 );
       
   181 
       
   182 
       
   183   // wait for them to exit
       
   184   pthread_join( threadhandle_send, NULL );
       
   185   pthread_join( threadhandle_recv, NULL );
       
   186 
       
   187 
       
   188   // return
       
   189   fprintf( stderr, "PG: pppdgateway has completed.\n" );
       
   190   return 0;
       
   191 }
       
   192 
       
   193   
       
   194 /*******************************************************************************
       
   195  *
       
   196  * receive_ppp_frames
       
   197  *
       
   198  ******************************************************************************/
       
   199 void *receive_ppp_frames( void *x )
       
   200 {
       
   201   int recvcount, writecount;
       
   202   char recvbuff[RECVBUFFSIZE];
       
   203 
       
   204   // listen on the udp socket and send anything received to stdout -- no framing is ever done on the input channel
       
   205   while( 1 ) {
       
   206 
       
   207     // wait for some data -- on error print error, close the socket, and exit. Closing the socket means that the other thread will clean up and exit
       
   208     recvcount = recv( sockfd, recvbuff, RECVBUFFSIZE, 0 );
       
   209     if( recvcount == -1 ) {
       
   210       fprintf( stderr, "PG: error occured while reading socket.\n" );
       
   211       closesocket( sockfd );
       
   212       pthread_exit( NULL );
       
   213     }
       
   214     //    fprintf( stderr, "PG: %d bytes incoming\n", recvcount );
       
   215 
       
   216     // send the data to the pppd server    
       
   217     writecount = fwrite( recvbuff, 1, recvcount, stdout );
       
   218     if( writecount != recvcount ) {
       
   219       fprintf( stderr, "PG: error occured while writing to stdout.\n" );
       
   220       closesocket( sockfd );
       
   221       pthread_exit( NULL );
       
   222     }
       
   223   }
       
   224 
       
   225   // done
       
   226   return NULL;
       
   227 }   
       
   228 
       
   229 
       
   230 /*******************************************************************************
       
   231  *
       
   232  * send_ppp_frames
       
   233  *
       
   234  ******************************************************************************/
       
   235 void *send_ppp_frames( void *x ) 
       
   236 {
       
   237   int err;
       
   238   int sendcount;
       
   239   int c = 0;
       
   240   
       
   241   // listen on stdin for data and write it to the socket -- on error print an error, closesocket, and exit. 
       
   242   while( 1 ) {
       
   243 
       
   244     // read the next char
       
   245     err = fread( &c, 1, 1, stdin );
       
   246     if( err != 1 ) {
       
   247       fprintf( stderr, "PG: error occured while reading from stdin.\n" );
       
   248       closesocket( sockfd );
       
   249       pthread_exit( NULL );
       
   250     }
       
   251     //    fprintf( stderr, "PG: %d bytes outgoing\n", err );
       
   252 
       
   253     // write it to the socket
       
   254     sendcount = send( sockfd, &c, 1, 0 );
       
   255     if( sendcount != 1 ) {
       
   256       fprintf( stderr, "PG: error occured while writing to the socket.\n" );
       
   257       closesocket( sockfd );
       
   258       pthread_exit( NULL );
       
   259     }
       
   260   }
       
   261 
       
   262   // done 
       
   263   return NULL;
       
   264 }
       
   265 
       
   266 
       
   267 /*******************************************************************************
       
   268  *
       
   269  * closesocket
       
   270  *
       
   271  ******************************************************************************/
       
   272 void closesocket( int sockfd )
       
   273 {
       
   274   shutdown( sockfd, SHUT_RDWR );
       
   275   close( sockfd );
       
   276 }
       
   277 
       
   278 
       
   279 /*******************************************************************************
       
   280  *
       
   281  * do_client_server_protocol()
       
   282  *
       
   283  ******************************************************************************/
       
   284 int do_client_server_protocol( int aMobsterDeviceID )
       
   285 {
       
   286   char c;
       
   287   int len, expected_length, i, err;
       
   288   char idstr[MAXIDSTR];
       
   289   char rpstr[MAXIDSTR];
       
   290 
       
   291   // construct the client string for the csprotocol
       
   292   snprintf( idstr, MAXIDSTR, "ID=%d", aMobsterDeviceID );
       
   293   len = strlen(idstr);
       
   294   idstr[len] = 0x0d;
       
   295   idstr[len+1] = 0;
       
   296 
       
   297 #ifdef SYSTEM_TEST_MP5
       
   298   assert( !"TEST" );
       
   299 #endif
       
   300 
       
   301   // send the string
       
   302   err = send( sockfd, idstr, len+1, 0 );
       
   303   if( err != (len+1) ) {
       
   304     fprintf( stderr, "PG: failed to write id string, exiting.\n" );
       
   305     return -1;
       
   306   }
       
   307   
       
   308   // construct the expected reply string to get the expected length
       
   309   snprintf( rpstr, MAXIDSTR, "SERVER(%d)", aMobsterDeviceID );
       
   310   expected_length = strlen(rpstr);
       
   311 
       
   312   // now read until there 
       
   313   for( i = 0; ; i++ ) {
       
   314 
       
   315     // read a byte
       
   316     err = recv( sockfd, &c, 1, 0 );
       
   317     if( err == -1 ) {
       
   318       fprintf( stderr, "PG: failed to read reply string (%d, %d).\n", err, errno );
       
   319       return -1;
       
   320     }
       
   321 
       
   322     // check for a mismatch
       
   323     if( c != rpstr[i] ) {
       
   324       fprintf( stderr, "PG: unexpected character from server.\n" );
       
   325       return -1;
       
   326     }
       
   327 
       
   328     // see if we've matched all chars
       
   329     if( (i+1) == expected_length ) {
       
   330       break;
       
   331     }
       
   332   }
       
   333 
       
   334   // done - success
       
   335   return 0;
       
   336 }