/***************************************************************************** ** ** ** Neversoft Entertainment ** ** ** ** Copyright (C) 1999 - All Rights Reserved ** ** ** ****************************************************************************** ** ** ** Project: GEL (Game Engine Library) ** ** ** ** Module: Net (OBJ) ** ** ** ** File name: net.cpp ** ** ** ** Created: 01/29/01 - spg ** ** ** ** Description: Network Manager code ** ** ** *****************************************************************************/ /***************************************************************************** ** Includes ** *****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #ifndef __PLAT_WN32__ #include #endif #ifdef __PLAT_XBOX__ //#include #include #endif #include #ifdef __PLAT_NGPS__ #include #include #endif /***************************************************************************** ** Externals ** *****************************************************************************/ /***************************************************************************** ** Defines ** *****************************************************************************/ //#define USE_DECI2 #define DEFAULT_SNPS2_SUB_MSK "255.255.255.0" #define DEFAULT_SNPS2_GATEWAY "192.168.0.1" const char spduartArgs[] = "-nogci\0dial=cdrom0:\\IOP\\DIAL_SPD.CNF;1"; /***************************************************************************** ** DBG Defines ** *****************************************************************************/ namespace Net { /***************************************************************************** ** Private Types ** *****************************************************************************/ /***************************************************************************** ** Private Data ** *****************************************************************************/ DefineSingletonClass( Manager, "Network Manager" ) #ifdef __PLAT_NGPS__ /* Set up the following list with one or more suitable DNS servers */ /*static const sn_char* dns_servers[] = { "205.147.0.100", "205.147.0.102", "" // List is terminated by null string };*/ static sn_char custom_built_script[SN_MAX_SCRIPT_LINES][SN_MAX_SCRIPT_LEN+1]; static const char *s_custom_isp_script[] = { "input 30 ogin:", /* Line 0 */ "output ", /* Line 1 */ "input 10 word:", /* Line 2 */ "output ", /* Line 3 */ "input 10 ing PPP", /* Line 4 */ "" /* script is terminated with null string */ }; #define vCUSTOM_USERNAME_LINE 1 #define vCUSTOM_PASSWORD_LINE 3 static bool s_cancel_dialup_conn; static int s_conn_semaphore; #endif // __PLAT_NGPS__ /***************************************************************************** ** Public Data ** *****************************************************************************/ /***************************************************************************** ** Private Prototypes ** *****************************************************************************/ /***************************************************************************** ** Private Functions ** *****************************************************************************/ /***************************************************************************** ** Private Functions ** *****************************************************************************/ #ifdef __PLAT_NGPS__ #define vPOWEROFF_STACK_SIZE (2 * 1024) static u_char s_poweroff_stack[vPOWEROFF_STACK_SIZE] __attribute__ ((aligned(16))); /******************************************************************/ /* The thread which waits for */ /* */ /******************************************************************/ static void s_power_off_thread(void *arg) { int sid = (int)arg; int stat; while( 1 ) { WaitSema(sid); // dev9 power off, need to power off PS2 //while( sceDevctl("dev9x:", DDIOC_OFF, NULL, 0, NULL, 0 ) < 0 ); while( sceDevctl("dev9x:", DDIOC_OFF, NULL, 0, NULL, 0 ) < 0 ); // PS2 power off while( !sceCdPowerOff( &stat ) || stat ); } } /******************************************************************/ /* */ /* */ /******************************************************************/ static void s_power_off_handler(void *arg) { int sid = (int)arg; iSignalSema(sid); } /******************************************************************/ /* */ /* */ /******************************************************************/ static void s_prepare_power_off(void) { struct ThreadParam tparam; struct SemaParam sparam; int tid, sid; sparam.initCount = 0; sparam.maxCount = 1; sparam.option = 0; sid = CreateSema(&sparam); tparam.stackSize = vPOWEROFF_STACK_SIZE; tparam.gpReg = &_gp; tparam.entry = s_power_off_thread; tparam.stack = (void *) s_poweroff_stack; tparam.initPriority = 1; tid = CreateThread( &tparam ); StartThread( tid, (void *) sid ); sceCdPOffCallback( s_power_off_handler, (void *) sid ); } /******************************************************************/ /* */ /* */ /******************************************************************/ static sn_int32 set_host_name( sn_char* host_name ) { sndev_set_dhost_type optval; sn_int32 host_size, r; Dbg_Assert( host_name ); host_size = strlen(host_name) + 1; // Check host_name isn't too big if (host_size > (sn_int32) sizeof(optval.host)) { Dbg_Printf("EE:set_host_name():error host_name too big\n"); return -1; } // I'm going to fill optval with zeros to start with, not strictly // necessary but this is only an example. memset(&optval,0,sizeof(optval)); // Fill in the optval structure optval.flags = 0; // Steve, you could set one of these two // values SN_DFLAG_EXCL_DIS or // SN_DFLAG_EXCL_REQ in the flags to // *exclude* either the discovery or // request message from the operation with // flags set to zero the option will be // applied to both messages if( host_name[0] == '\0' ) { Dbg_Printf( "Clearing Host Name Option\n" ); optval.clear_option = 1; // Steve, you would set this to 1 if you // wanted to remove the host name } else { Dbg_Printf( "Setting Host Name Option to %s\n", host_name ); optval.clear_option = 0; } optval.include_null = 0; // Steve, if you wanted the null terminator // included in the host name that's sent in // the DHCP msg you would set this to 1 optval.reserved = 0; // Must be 0 memcpy(optval.host, host_name, host_size); // Send the option to the IOP r = sndev_set_options(0, SN_DEV_SET_DHOST, &optval, sizeof(optval)); if (r != 0) { Dbg_Printf("EE:sndev_set_options():error %d\n",r); return -1; } return 0; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool Manager::stop_stack( void ) { int result, stack_state; Dbg_Printf( "EE:Stopping the TCP/IP stack\n" ); result = sn_stack_state(SN_STACK_STATE_STOP, &stack_state); if( result != 0 ) { Dbg_Printf( "EE:sn_stack_sate() failed %d\n", result ); SetError( vRES_ERROR_GENERAL ); return false; } Dbg_Printf( "EE:Stack Stopped\n" ); return true; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool Manager::start_stack( void ) { sn_int32 result, stack_state; Tmr::Time start_time; // Start the stack Dbg_Printf("EE:Starting the TCP/IP stack\n"); result = sn_stack_state( SN_STACK_STATE_START, &stack_state ); if( result != 0 ) { Dbg_Printf( "EE:sn_stack_sate() failed %d\n", result ); SetError( vRES_ERROR_GENERAL ); return false; } Dbg_Printf( "EE:Stack Started\n" ); if(( GetConnectionType() == vCONN_TYPE_MODEM ) || ( GetConnectionType() == vCONN_TYPE_PPPOE )) { int modem_state, prev_modem_state; Tmr::Time start_time; modem_state = -1; // Invalid prev_modem_state = -2; // Ivalid and != modem_state start_time = Tmr::GetTime(); Dbg_Printf( "EE:Calling snmdm_get_state() - until modem ready\n" ); while( modem_state != SN_MODEM_READY ) { result = snmdm_get_state( &modem_state ); if (result != 0) { Dbg_Printf("EE:snmdm_get_state() failed %d\n", result); SetError( vRES_ERROR_DEVICE_NOT_CONNECTED ); return false; } if (modem_state == prev_modem_state) { sn_delay(10); } else { prev_modem_state = modem_state; Dbg_Printf(" Modem state = %d %s\n", modem_state, sntc_str_modem_state( modem_state )); } // After 5 seconds, time out and say there was no dialtone if(( Tmr::GetTime() - start_time ) > Tmr::Seconds( 10 )) { SetError( vRES_ERROR_DEVICE_NOT_CONNECTED ); return false; } } Dbg_Printf( "EE:Ready\n" ); } // Wait for the stack to come up Dbg_Printf( "EE:Waiting for socket API to be ready\n" ); start_time = Tmr::GetTime(); while( sn_socket_api_ready() == SN_FALSE ) { // Delay to avoid hogging the processor sn_delay( 500 ); if(( Tmr::GetTime() - start_time ) > Tmr::Seconds( 10 )) { Dbg_Printf( "EE:Timed out waiting for socket API to be ready\n" ); return false; } } if( ShouldUseDHCP()) { struct hostent* hentp = NULL; sn_bool got_ip_addr = SN_FALSE; struct in_addr ip_addr; Dbg_Printf( "EE:Waiting for DHCP server to supply IP addr etc\n" ); start_time = Tmr::GetTime(); do { // A way of getting the local IP address hentp = gethostbyname(LOCAL_NAME); if(( hentp != NULL ) && ( hentp->h_addr_list[0] != NULL )) { // Read the IP address from the hostent struct memcpy( &ip_addr,hentp->h_addr_list[0], sizeof( ip_addr )); if( ip_addr.s_addr != 0 ) { got_ip_addr = SN_TRUE; Dbg_Printf( "DHCP allocated IP addr %s\n", inet_ntoa( ip_addr )); } } // Delay to avoid hogging the processor if( got_ip_addr == SN_FALSE ) { sn_delay(500); } if(( Tmr::GetTime() - start_time ) > Tmr::Seconds( 10 )) { Dbg_Printf( "EE:Timed out waiting for DHCP response\n" ); SetError( vRES_ERROR_DHCP ); return false; } } while( got_ip_addr == SN_FALSE ); strcpy( m_local_ip, inet_ntoa( ip_addr )); } return true; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool Manager::setup_ethernet_params( void ) { sndev_set_ether_ip_type params; int result; if( ShouldUseDHCP()) { Dbg_Printf( "\n\n\n*********************** USING DHCP ******************* \n\n\n" ); memset( ¶ms,0, sizeof( params )); } else { inet_aton( GetLocalIP(), (struct in_addr*) ¶ms.ip_addr ); Dbg_Printf( "======================== Ip is %d : %d\n", params.ip_addr, htonl( params.ip_addr )); inet_aton( GetSubnetMask(), (struct in_addr*) ¶ms.sub_mask ); inet_aton( GetGateway(), (struct in_addr*) ¶ms.gateway ); } result = sndev_set_options( 0, SN_DEV_SET_ETHER_IP, ¶ms, sizeof(params)); if( result != 0 ) { Dbg_Printf( "EE:Error sndev_set_options() returned %d\n", result ); SetError( vRES_ERROR_GENERAL ); return false; } if( ShouldUseDHCP()) { result = set_host_name( m_host_name ); if( result != 0 ) { SetError( vRES_ERROR_GENERAL ); return false; } } return true; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool Manager::initialize_device( void ) { sn_int32 result; sn_int32 device_type; sn_int16 idVendor; sn_int16 idProduct; sn_bool first_time; Tmr::Time start_time; Tmr::Time timeout; // Initialise the socket API, if fails print error and return Dbg_Printf( "EE:Initialising socket API\n" ); result = sockAPIinit( 6 ); if( ( result != 0 ) && ( result != SN_EALRDYINIT )) { Dbg_Printf( "EE:sockAPIinit() failed %d\n", result ); SetError( vRES_ERROR_GENERAL ); return false; } // If we've already init'd the sockets API, don't re-register this thread // just let it run through the rest of setup if( result != SN_EALRDYINIT ) { // Register this thread with the socket API result = sockAPIregthr(); if (result != 0) { Dbg_Printf( "EE:sockAPIregthr() failed %d\n", result ); SetError( vRES_ERROR_GENERAL ); return false; } } // Now wait for DECI2 'device' to be 'attached' device_type = SN_DEV_TYPE_NONE; first_time = SN_TRUE; start_time = Tmr::GetTime(); // It takes longer to init the sony modem if( GetDeviceType() == vDEV_TYPE_SONY_MODEM ) { timeout = Tmr::Seconds( 15 ); } else { timeout = Tmr::Seconds( 10 ); } while( device_type == SN_DEV_TYPE_NONE ) { result = sndev_get_attached( 0, &device_type, &idVendor, &idProduct ); if( result != 0 ) { Dbg_Printf( "EE:sndev_get_attached() failed %d\n", result ); SetError( vRES_ERROR_GENERAL ); return false; } if( device_type == SN_DEV_TYPE_NONE ) { if( first_time == SN_TRUE ) { first_time = SN_FALSE; Dbg_Printf( "EE:Waiting for network device to be attached ...\n" ); } sn_delay( 10 ); } if(( Tmr::GetTime() - start_time ) > timeout ) { Dbg_Printf( "EE:Timed out waiting for network device to be attached\n" ); break; } } switch( device_type ) { case SN_DEV_TYPE_DECI2: Dbg_Printf( "Using DECI-2 ethernet emulation\n" ); break; case SN_DEV_TYPE_USB_MODEM: Dbg_Printf("EE:USB-Modem Attached (idVendor=0x%04X idProduct=0x%04X)\n", ((int)idVendor) & 0xFFFF, ((int)idProduct) & 0xFFFF); break; case SN_DEV_TYPE_USB_ETHER: Dbg_Printf("EE:USB-Ethernet Attached (idVendor=0x%04X idProduct=0x%04X)\n", ((int)idVendor) & 0xFFFF, ((int)idProduct) & 0xFFFF); break; default: { if( idVendor == 0 ) { Dbg_Printf( "Unknown Device %d\n", device_type ); SetError( vRES_ERROR_UNKNOWN_DEVICE ); } else { Dbg_Assert( idVendor == 1 ); SetError( vRES_ERROR_DEVICE_NOT_HOT ); } return false; } } return true; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool Manager::sn_stack_setup( void ) { // Set up the list of DNS servers char* dns_servers[3]; int result, i; sn_int32 stack_state; sn_stack_state( SN_STACK_STATE_READ, &stack_state ); if( stack_state == SN_STACK_STATE_START ) { if( stop_stack() == false ) { return false; } } if( GetConnectionType() == vCONN_TYPE_ETHERNET ) { if(( setup_ethernet_params() == false )) { return false; } } for( i = 0; i < 3; i++ ) { dns_servers[i] = m_dns_servers[i]; Dbg_Printf( "DNS Server %d is %s\n", i, dns_servers[i] ); } result = sntc_set_dns_server_list((const sn_char**) dns_servers); if( result != 0 ) { Dbg_Printf( "EE:sntc_set_dns_server_list() failed %d\n", result ); SetError( vRES_ERROR_GENERAL ); return false; } if( GetConnectionType() == vCONN_TYPE_PPPOE ) { sndev_set_pppoe_opt_type pppoe; // Enable PPPoE pppoe.flags = 1; Dbg_Printf( "Enabling PPPoE\n" ); result = sndev_set_options( 0, SN_DEV_SET_PPPOE_OPT, &pppoe, sizeof(pppoe)); Dbg_Printf( "EE:sndev_set_options(pppoe) returned %d\n", result ); } if(( GetConnectionType() == vCONN_TYPE_MODEM ) || ( GetConnectionType() == vCONN_TYPE_PPPOE )) { // Now, we have a valid modem. Try to initialize //result = snmdm_set_mdm_init( "AT&F S0=0" ); result = snmdm_set_mdm_init( "AT&F S0=0 W2" ); if( result != 0 ) { Dbg_Printf( "EE:snmdm_set_mdm_init() failed %d\n", result ); SetError( vRES_ERROR_DEVICE_NOT_CONNECTED ); return false; } Dbg_Printf( "EE:snmdm_set_mdm_init() worked ok\n" ); } if( start_stack() == false ) { return false; } m_options_changed = false; return true; } /******************************************************************/ /* */ /* */ /******************************************************************/ static sn_int32 custom_construct_script( sn_int32 isp_type, sn_char* user_name, sn_char* password) { sn_int32 line_index; sn_bool copy_done; copy_done = SN_FALSE; line_index = 0; // Copy the preset script to custom_built_script while( copy_done == SN_FALSE ) { // Copy this line of the script strcpy( custom_built_script[line_index], s_custom_isp_script[line_index] ); // If this line was a null string then finished copy if( s_custom_isp_script[line_index][0] == 0 ) { copy_done = SN_TRUE; } else { line_index++; } } sn_strcat( custom_built_script[vCUSTOM_USERNAME_LINE], user_name ); sn_strcat( custom_built_script[vCUSTOM_USERNAME_LINE], "\\r" ); // Concatenate password\r on to line index CUSTOM_PASSWORD_LINE sn_strcat( custom_built_script[vCUSTOM_PASSWORD_LINE], password ); sn_strcat( custom_built_script[vCUSTOM_PASSWORD_LINE], "\\r" ); return 0; // Success } /******************************************************************/ /* */ /* */ /******************************************************************/ sn_int32 custom_connect_modem( sn_char* phone_no, sn_int32 isp_type, sn_char* user_name, sn_char* password, sn_int32 timeout_secs, sntc_mdmstate_callback callback ) { sn_int32 result; sn_int32 modem_state; sn_bool done_script; sn_int32 script_index; sn_int32 prev_modem_state; sn_bool connect_started; sn_int32 timeout_ms; sn_int32 connect_err; result = snmdm_set_phone_no( phone_no ); // Check that the above function call worked ok if( result != 0 ) { Dbg_Printf( "Failed to set phone number: %d\n", result ); return SNTC_ERR_MDMAPI; } // Construct the log in script file (in custom_built_script) result = custom_construct_script( isp_type, user_name, password ); if( result != 0 ) { Dbg_Printf( "Failed to build login script: %d\n", result ); return SNTC_ERR_BSCRIPT; } // Store the log in script file via the modem API // Send a null string first, this resets the script write ptr to 0, // it should already be at 0, but just being defensive. result = snmdm_set_script(""); if( result != 0 ) { Dbg_Printf( "snmdm_set_script() failed: %d\n", result ); return SNTC_ERR_MDMAPI; } // Now send the script file to the modem API script_index = 0; done_script = SN_FALSE; while( done_script == SN_FALSE ) { result = snmdm_set_script( custom_built_script[ script_index ] ); if( result != 0 ) { Dbg_Printf( "snmdm_set_script() failed: %d\n", result ); return SNTC_ERR_MDMAPI; } // Check for null line, which is last line if( custom_built_script[script_index][0] == 0 ) { done_script = SN_TRUE; } else { script_index++; } } // Everything is ready, so ask the modem to connect result = snmdm_connect(); if( result != 0 ) { Dbg_Printf( "snmdm_connect() failed: %d\n", result ); return SNTC_ERR_MDMAPI; } // Now wait for the modem to become connected modem_state = -1; /* Invalid */ prev_modem_state = -2; /* Ivalid and != modem_state */ connect_started = SN_FALSE; timeout_ms = timeout_secs * 1000; while(( modem_state != SN_MODEM_PPP_UP ) && ( s_cancel_dialup_conn == false )) { // Get the current state of the modem link result = snmdm_get_state(&modem_state); if( result != 0 ) { Dbg_Printf( "snmdm_get_state() failed: %d\n", result ); return SNTC_ERR_MDMAPI; } // Monitor for modem connection process starting, then if it // goes back to ready we know it's failed to connect. if( connect_started == SN_FALSE ) { // Any of the following means modem connection started if( (modem_state == SN_MODEM_DIALING) ||(modem_state == SN_MODEM_LOGIN) ||(modem_state == SN_MODEM_CONNECTED) ||(modem_state == SN_MODEM_PPP_UP)) { connect_started = SN_TRUE; } } else { // Having started the connection, then unless it's in // one of the following states it's failed to connect if( (modem_state != SN_MODEM_DIALING) &&(modem_state != SN_MODEM_LOGIN) &&(modem_state != SN_MODEM_CONNECTED) &&(modem_state != SN_MODEM_PPP_UP)) { // Read the reason why the connect failed. result = snmdm_get_connect_err( &connect_err ); if( result != 0 ) { Dbg_Printf( "snmdm_get_connect_err() failed: %d\n", result ); return SNTC_ERR_MDMAPI; } switch( connect_err ) { case SN_CONERR_BUSY: Dbg_Printf( "Busy\n" ); return SNTC_ERR_BUSY; break; case SN_CONERR_NOCARRIER: Dbg_Printf( "No carrier\n" ); return SNTC_ERR_NOCARRIER; break; case SN_CONERR_NOANSWER: Dbg_Printf( "No answer\n" ); return SNTC_ERR_NOANSWER; break; case SN_CONERR_NODIALTONE: Dbg_Printf( "No dialtone\n" ); return SNTC_ERR_NODIALTONE; break; default: Dbg_Printf( "connect started then modem state=sntc_str_modem_state(modem_state)\n" ); return SNTC_ERR_CONNECT; } } } // Now check whether the modem state has changed since the // previous time round this loop, and if so call the user // callback function (unless it's NULL), otherwise check // for time-out / do a delay if( modem_state != prev_modem_state ) { prev_modem_state = modem_state; if( callback != NULL ) { (*callback)(modem_state); } } else { if( timeout_ms <= 0 ) { Dbg_Printf( "Connect timed out in modem state %s\n", sntc_str_modem_state(modem_state) ); return SNTC_ERR_TIMEOUT; } sn_delay( 10 ); timeout_ms -= 10; } } // If we get to here, the modem has successfully connected Dbg_Printf( "Connected!\n" ); return 0; } /******************************************************************/ /* */ /* */ /******************************************************************/ void Manager::threaded_modem_conn( void *data ) { Manager* man = (Manager *) data; int result; Dbg_Printf( "Registering modem thread %d with stack\n", GetThreadId()); result = sockAPIregthr(); Dbg_Assert( result == 0 ); WaitSema( s_conn_semaphore ); Dbg_Printf("EE:Calling sntc_connect_modem()\n"); // Set the script write pointer back to zero result = snmdm_set_script(""); // Set up Authentication parameters. sndev_set_chap_type ChapOptions = {0}; ChapOptions.accept_chap = man->ShouldUseDialupAuthentication(); Dbg_Printf( "Setting chap to %d\n", ChapOptions.accept_chap ); ChapOptions.require_chap = 0; strcpy(ChapOptions.locl_name, man->m_isp_user_name ); strcpy(ChapOptions.locl_secr, man->m_isp_password ); strcpy(ChapOptions.chal_name,"*"); // Accept any challenge name Dbg_Printf( "Chap username: %s password: %s\n", man->m_isp_user_name, man->m_isp_password ); result = sndev_set_options( 0, SN_DEV_SET_CHAP, &ChapOptions, sizeof(ChapOptions)); Dbg_Printf( "EE:sndev_set_options(SN_DEV_SET_CHAP) returned %d\n", result ); sndev_set_pap_type PapOptions = {0}; PapOptions.accept_pap = man->ShouldUseDialupAuthentication(); Dbg_Printf( "Setting pap to %d\n", PapOptions.accept_pap ); PapOptions.require_pap = 0; strcpy(PapOptions.locl_name, man->m_isp_user_name ); strcpy(PapOptions.locl_pass, man->m_isp_password ); Dbg_Printf( "Pap username: %s password: %s\n", man->m_isp_user_name, man->m_isp_password ); result = sndev_set_options( 0, SN_DEV_SET_PAP, &PapOptions, sizeof(PapOptions)); Dbg_Printf( "EE:sndev_set_options(SN_DEV_SET_PAP) returned %d\n", result ); man->m_modem_err = 0; if( man->GetConnectionType() == vCONN_TYPE_MODEM ) { Dbg_Printf( "Dialing %s user: %s pass: %s\n", man->m_isp_phone_no, man->m_isp_user_name, man->m_isp_password ); result = custom_connect_modem ( man->m_isp_phone_no, // phone_no SNTC_ISP_GENERIC, // isp_type man->m_isp_user_name, // user_name man->m_isp_password, // password vMODEM_CONNECT_TIMEOUT, // timeout_secs man->conn_modem_state_callback );// callback } else if( man->GetConnectionType() == vCONN_TYPE_PPPOE ) { result = custom_connect_modem ( "", // phone_no 0, // isp_type "", // user_name "", // password vMODEM_CONNECT_TIMEOUT, // timeout_secs man->conn_modem_state_callback );// callback } // Check whether connection succeeded if( result == 0 ) { sn_int32 result, statval, statlen; statval = 1234; // so can see it's modified statlen = sizeof(statval); result = sndev_get_status(0, SN_DEV_STAT_BAUD, &statval, &statlen); man->m_modem_baud_rate = statval; man->m_online = true; } else { sntc_disconnect_modem( vMODEM_DISCONNECT_TIMEOUT, // timeout_secs NULL, // callback NULL ); // error_message man->SetModemState( vMODEM_STATE_ERROR ); man->m_modem_err = result; Dbg_Printf( "EE:sntc_connect_modem() failed: %d\n", result ); man->m_online = false; } Dbg_Printf( "DeRegistering modem thread %d with stack\n", GetThreadId()); sockAPIderegthr(); SignalSema( s_conn_semaphore ); } /******************************************************************/ /* */ /* */ /******************************************************************/ void Manager::threaded_modem_disconn( void *data ) { Manager* man = (Manager *) data; sn_char* err_msg_ptr; bool modem_disconnected; int result; Dbg_Printf( "Registering modem thread %d with stack\n", GetThreadId()); result = sockAPIregthr(); Dbg_Assert( result == 0 ); modem_disconnected = false; if( man->m_online ) { Dbg_Printf( "EE:Calling sntc_disconnect_modem()\n" ); result = sntc_disconnect_modem( vMODEM_DISCONNECT_TIMEOUT, // timeout_secs disconn_modem_state_callback, // callback &err_msg_ptr ); // error_message // Check whether disconnection succeeded if (result == 0) { Dbg_Printf("EE:sntc_disconnect_modem() worked:%s\n",err_msg_ptr); modem_disconnected = true; } else { Dbg_Printf("EE:sntc_disconnect_modem() failed:%s\n",err_msg_ptr); modem_disconnected = false; } } // If the modem didn't connect and disconnect ok, then reset it if( !modem_disconnected ) { bool modem_reset; do { Dbg_Printf( "EE:Calling sntc_reset_modem()\n" ); result = sntc_reset_modem ( vMODEM_RESET_TIMEOUT, // timeout_secs disconn_modem_state_callback, // callback &err_msg_ptr ); // error_message // Check whether reset succeeded if( result == 0 ) { Dbg_Printf( "EE:sntc_reset_modem() worked:%s\n", err_msg_ptr ); modem_reset = true; } else { Dbg_Printf( "EE:sntc_reset_modem() failed:%s\n", err_msg_ptr ); modem_reset = false; // If their modem is no longer plugged in, just consider it "hung up" if( result == SNTC_ERR_NOMODEM ) { break; } sn_delay( 1000 ); // avoid excessive printf if unplugged } } while( !modem_reset ); } man->SetModemState( vMODEM_STATE_DISCONNECTED ); man->m_online = false; Dbg_Printf( "DeRegistering modem thread %d with stack\n", GetThreadId()); sockAPIderegthr(); } #endif // __PLAT_NGPS__ /***************************************************************************** ** Public Functions ** *****************************************************************************/ /******************************************************************/ /* Add logic tasks to the current task list */ /* */ /******************************************************************/ void Manager::AddLogicTasks( App* app ) { Mlp::Manager * mlp_manager = Mlp::Manager::Instance(); mlp_manager->AddLogicTask( app->GetReceiveDataTask()); mlp_manager->AddLogicTask( app->GetSendDataTask()); mlp_manager->AddLogicTask( app->GetProcessDataTask()); mlp_manager->AddLogicTask( app->GetNetworkMetricsTask()); } /******************************************************************/ /* Add logic tasks to the push logic task list */ /* */ /******************************************************************/ void Manager::AddLogicPushTasks( App* app ) { Mlp::Manager * mlp_manager = Mlp::Manager::Instance(); app->GetSendDataTask().Remove(); app->GetReceiveDataTask().Remove(); app->GetProcessDataTask().Remove(); app->GetNetworkMetricsTask().Remove(); mlp_manager->AddLogicPushTask( app->GetReceiveDataTask()); mlp_manager->AddLogicPushTask( app->GetSendDataTask()); mlp_manager->AddLogicPushTask( app->GetProcessDataTask()); mlp_manager->AddLogicPushTask( app->GetNetworkMetricsTask()); } /******************************************************************/ /* Removes network logic tasks */ /* */ /******************************************************************/ void Manager::RemoveNetworkTasks( App* app ) { app->GetSendDataTask().Remove(); app->GetReceiveDataTask().Remove(); app->GetProcessDataTask().Remove(); app->GetNetworkMetricsTask().Remove(); } /******************************************************************/ /* Creates a new Server at the given address and port */ /* */ /******************************************************************/ Server* Manager::CreateNewAppServer( int id, char* appName, int max_clients, unsigned short port, int address, int flags ) { Server *new_app; Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap()); // If we're using DHCP, we should have gotten our real IP address by now // from the DHCP server. Use that address from now on if( ShouldUseDHCP()) { address = inet_addr( m_local_ip ); } new_app = new Server( flags ); new_app->m_net_man = this; new_app->init(); new_app->m_id = id; strncpy( new_app->m_name, appName, MAX_LEN_APP_NAME ); new_app->m_max_connections = max_clients; m_net_servers.AddToTail( &new_app->m_node ); if( new_app->IsLocal()) { new_app->m_connected = true; } else { new_app->bind_app_socket( address, port ); if( flags & App::mBROADCAST ) { new_app->m_connected = true; } } #ifdef USE_ALIASES if( flags & App::mALIAS_SUPPORT ) { new_app->AllocateAliasTables(); new_app->ClearAliasTables(); } #endif AddLogicTasks( new_app ); #ifndef __PLAT_NGC__ Dbg_Printf( "Created new: %s server %p, Max Clients: %d, IP: %s, Port: %d", appName, new_app, max_clients, inet_ntoa( *(struct in_addr*) &address ), port ); #endif // __PLAT_NGC__ m_num_apps++; Mem::Manager::sHandle().PopContext(); return new_app; } /******************************************************************/ /* Creates a new client socket */ /* */ /******************************************************************/ Client *Manager::CreateNewAppClient( int id, char* appName, unsigned short port, int address, int flags ) { Client *new_app; Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().NetworkHeap()); // If we're using DHCP, we should have gotten our real IP address by now // from the DHCP server. Use that address from now on if( ShouldUseDHCP()) { address = inet_addr( m_local_ip ); } new_app = new Client( flags ); strncpy( new_app->m_name, appName, MAX_LEN_APP_NAME ); new_app->m_net_man = this; new_app->init(); new_app->m_id = id; new_app->m_max_connections = 1; m_net_clients.AddToTail( &new_app->m_node ); if( !new_app->IsLocal()) { #ifndef __PLAT_XBOX__ new_app->bind_app_socket( address, port ); #endif } #ifdef USE_ALIASES new_app->ClearAliasTable(); #endif AddLogicTasks( new_app ); Dbg_Printf( "Created new: %s client %p on port %d\n", appName, new_app, port ); m_num_apps++; Mem::Manager::sHandle().PopContext(); return new_app; } /******************************************************************/ /* */ /* */ /******************************************************************/ void Manager::DestroyApp( App *app ) { app->m_node.Remove(); app->ShutDown(); delete app; m_num_apps--; } /******************************************************************/ /* */ /* */ /******************************************************************/ Metrics::Metrics( void ) { m_num_packets = 0; m_total_bytes = 0; m_bytes_per_sec = 0; memset( m_num_messages, 0, sizeof( int ) * MAX_MSG_IDS ); memset( m_size_messages, 0, sizeof( int ) * MAX_MSG_IDS ); } /******************************************************************/ /* */ /* */ /******************************************************************/ void Metrics::CalculateBytesPerSec( int cur_time ) { int i, num_bytes; num_bytes = 0; // Sum up number of bytes transferred over the last second for( i = 0; i < vNUM_BUFFERED_PACKETS; i++ ) { if( i >= m_num_packets ) { break; } if(( cur_time - m_packets[i].GetTime()) < (int) Tmr::Seconds( 1 )) { num_bytes += m_packets[i].GetNumBytes(); } } m_bytes_per_sec = num_bytes; } /******************************************************************/ /* */ /* */ /******************************************************************/ int Metrics::GetBytesPerSec( void ) { return m_bytes_per_sec; } /******************************************************************/ /* */ /* */ /******************************************************************/ int Metrics::GetTotalBytes( void ) { return m_total_bytes; } /******************************************************************/ /* */ /* */ /******************************************************************/ int Metrics::GetTotalMessageData( int msg_id ) { return m_size_messages[ msg_id ]; } /******************************************************************/ /* */ /* */ /******************************************************************/ int Metrics::GetTotalNumMessagesOfId( int msg_id ) { return m_num_messages[ msg_id ]; } /******************************************************************/ /* */ /* */ /******************************************************************/ void Metrics::AddPacket( int size, int time ) { int index; index = m_num_packets % vNUM_BUFFERED_PACKETS; m_packets[ index ].SetNumBytes( size ); m_packets[ index ].SetTime( time ); m_total_bytes += size; m_num_packets++; } /******************************************************************/ /* */ /* */ /******************************************************************/ void Metrics::AddMessage( int msg_id, int size ) { m_num_messages[ msg_id ]++; m_size_messages[ msg_id ] += size; } /******************************************************************/ /* */ /* */ /******************************************************************/ int PacketInfo::GetNumBytes( void ) { return m_num_bytes; } /******************************************************************/ /* */ /* */ /******************************************************************/ int PacketInfo::GetTime( void ) { return m_time; } /******************************************************************/ /* */ /* */ /******************************************************************/ void PacketInfo::SetNumBytes( int size ) { m_num_bytes = size; } /******************************************************************/ /* */ /* */ /******************************************************************/ void PacketInfo::SetTime( int time ) { m_time = time; } /******************************************************************/ /* Iterator */ /* */ /******************************************************************/ Server *Manager::FirstServer( Lst::Search< App > *sh ) { Dbg_Assert( sh ); return((Server*) sh->FirstItem( m_net_servers )); } /******************************************************************/ /* Iterator */ /* */ /******************************************************************/ Client *Manager::FirstClient( Lst::Search< App > *sh ) { Dbg_Assert( sh ); return((Client*) sh->FirstItem( m_net_clients )); } /******************************************************************/ /* Iterator */ /* */ /******************************************************************/ App *Manager::NextApp( Lst::Search< App > *sh ) { Dbg_Assert( sh ); return( sh->NextItem()); } /******************************************************************/ /* */ /* */ /******************************************************************/ int Manager::NumApps( void ) { return m_num_apps; } /******************************************************************/ /* */ /* */ /******************************************************************/ #ifdef __PLAT_NGC__ static void* s_so_alloc( u32 name, s32 size ) { return Mem::Malloc( size ); } /******************************************************************/ /* */ /* */ /******************************************************************/ static void s_so_free( u32 name, void* ptr, s32 size ) { Mem::Free( ptr ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool Manager::initialize_ngc( void ) { int result; SOConfig config; memset( &config, 0, sizeof( SOConfig )); config.vendor = SO_VENDOR_NINTENDO; config.version = SO_VERSION; config.alloc = s_so_alloc; config.free = s_so_free; if( ShouldUseDHCP()) { config.flag = SO_FLAG_DHCP; } else { config.flag = 0; inet_aton( GetLocalIP(), (struct in_addr*) &config.addr ); inet_aton( GetSubnetMask(), (struct in_addr*) &config.netmask ); inet_aton( GetGateway(), (struct in_addr*) &config.router ); inet_aton( GetDNSServer( 0 ), (struct in_addr*) &config.dns1 ); inet_aton( GetDNSServer( 1 ), (struct in_addr*) &config.dns2 ); } result = SOStartup( &config ); if( result != 0 ) { SOCleanup(); return false; } return true; } #endif /******************************************************************/ /* */ /* */ /******************************************************************/ #ifdef __PLAT_NGPS__ bool Manager::load_irx_files( void ) { ////////////////////////////// #if 0 // MOVED TO SIOMAN.CPP int result; // Load the stack IRX file #ifdef __NOPT_DEBUG__ result = SIO::LoadIRX( "SNSTKDBG" ); #else result = SIO::LoadIRX( "SNSTKREL" ); #endif if( result < 0 ) { Dbg_MsgAssert( 0,( "EE:Can't load module snstkrel/dbg.irx. Error : %d\n", result )); SetError( vRES_ERROR_INVALID_IRX ); return false; } #endif ////////////////////////////// #ifdef USE_DECI2 // Load the DECI2 driver IRX file SIO::LoadIRX( "sndrv000" ); #else switch( GetConnectionType()) { case vCONN_TYPE_PPPOE: { switch( GetDeviceType()) { case vDEV_TYPE_USB_ETHERNET: { // Load the PPPoE Driver IRX file if( SIO::LoadIRX( "sndrv200" ) < 0 ) { SetError( vRES_ERROR_DEVICE_NOT_CONNECTED ); return false; } // Load the USB-Ethernet Driver IRX file if( SIO::LoadIRX( "sndrv201" ) < 0 ) { SetError( vRES_ERROR_DEVICE_NOT_CONNECTED ); return false; } break; } case vDEV_TYPE_PC_ETHERNET: { // Load the PPPoE Driver IRX file if( SIO::LoadIRX( "sndrv200" ) < 0 ) { SetError( vRES_ERROR_DEVICE_NOT_CONNECTED ); return false; } // Load the SN Wrapper (PPPoE variant) for Sony Ether if( SIO::LoadIRX( "sndrv202" ) < 0 ) { SetError( vRES_ERROR_DEVICE_NOT_CONNECTED ); return false; } // Load the Sony pcmcia irx if( SIO::LoadIRX( "dev9" ) < 0 ) { SetError( vRES_ERROR_DEVICE_NOT_CONNECTED ); return false; } s_prepare_power_off(); // Load the Sony Ethernet driver IRX file if( SIO::LoadIRX( "smap", 0, NULL, false ) < 0 ) { SetError( vRES_ERROR_DEVICE_NOT_CONNECTED ); return false; } break; } default: SetError( vRES_ERROR_GENERAL ); return false; } break; } case vCONN_TYPE_ETHERNET: { switch( GetDeviceType()) { case vDEV_TYPE_USB_ETHERNET: { // Load the USB-Ethernet Driver IRX file if( SIO::LoadIRX( "sndrv001" ) < 0 ) { SetError( vRES_ERROR_DEVICE_NOT_CONNECTED ); return false; } break; } case vDEV_TYPE_PC_ETHERNET: { if( SIO::LoadIRX( "sndrv100" ) < 0 ) { SetError( vRES_ERROR_DEVICE_NOT_CONNECTED ); return false; } // Load the Sony pcmcia irx if( SIO::LoadIRX( "dev9" ) < 0 ) { SetError( vRES_ERROR_DEVICE_NOT_CONNECTED ); return false; } s_prepare_power_off(); // Load the Sony Ethernet driver IRX file if( SIO::LoadIRX( "smap", 0, NULL, false ) < 0 ) { SetError( vRES_ERROR_DEVICE_NOT_CONNECTED ); return false; } break; } default: SetError( vRES_ERROR_GENERAL ); return false; } break; } case vCONN_TYPE_MODEM: { switch( GetDeviceType()) { case vDEV_TYPE_USB_MODEM: { // Load the USB-Modem Driver IRX file if( SIO::LoadIRX( "sndrv002" ) < 0 ) { SetError( vRES_ERROR_DEVICE_NOT_CONNECTED ); return false; } break; } case vDEV_TYPE_SONY_MODEM: { if (Config::PAL()) { // Sony Modem Not Supported in PAL territories SetError( vRES_ERROR_DEVICE_NOT_CONNECTED ); return false; } // Load the SN modem wrapper irx if( SIO::LoadIRX( "sndrv101" ) < 0 ) { SetError( vRES_ERROR_DEVICE_NOT_CONNECTED ); return false; } // Load the Sony pcmcia irx if( SIO::LoadIRX( "dev9" ) < 0 ) { SetError( vRES_ERROR_DEVICE_NOT_CONNECTED ); return false; } s_prepare_power_off(); // Load the Sony modem driver irx if( SIO::LoadIRX( "spduart", sizeof(spduartArgs), (char*) spduartArgs ) < 0 ) { SetError( vRES_ERROR_DEVICE_NOT_CONNECTED ); return false; } break; } default: SetError( vRES_ERROR_GENERAL ); return false; } break; } default: // No valid device specified SetError( vRES_ERROR_GENERAL ); return false; } #endif // USE_DECI2 return true; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool Manager::initialize_ps2( void ) { bool result; Dbg_Printf( "initializing PS2\n" ); if( m_net_drivers_loaded == false ) { bool success; File::StopStreaming( ); if ( Pcm::UsingCD( ) ) { Dbg_MsgAssert( 0,( "Can't load IRX modules when CD is busy." )); return false; } Dbg_Printf( "initializing PS2_2\n" ); success = load_irx_files(); m_net_drivers_loaded = true; if( success == false ) { return false; } } else { if( m_device_changed ) { SetError( vRES_ERROR_DEVICE_CHANGED ); return false; } } result = initialize_device(); if( result == false ) { return false; } if( !m_stack_setup || m_options_changed ) { m_stack_setup = sn_stack_setup(); } m_device_changed = false; return m_stack_setup; } #endif // __PLAT_NGPS__ /******************************************************************/ /* */ /* */ /******************************************************************/ Manager::Manager( void ) { int msg_id, i; #if( defined ( __PLAT_WN32__ ) || defined ( __PLAT_XBOX__ )) int err; WORD version_required; WSADATA wsa_data; #ifdef __PLAT_XBOX__ XNetStartupParams xnsp; ZeroMemory( &xnsp, sizeof(xnsp) ); xnsp.cfgSizeOfStruct = sizeof(xnsp); #ifdef __NOPT_NOASSERTIONS__ xnsp.cfgFlags = 0; #else xnsp.cfgFlags = XNET_STARTUP_BYPASS_SECURITY;// | XNET_STARTUP_BYPASS_DHCP; #endif err = XNetStartup( &xnsp ); if( err ) { XNetCleanup(); return; } #endif version_required = MAKEWORD( 2, 2 ); if( err = WSAStartup ( version_required, &wsa_data )) { Dbg_MsgAssert( 0,( "Failed to start WinSock\n" )); WSACleanup(); #ifdef __PLAT_XBOX__ XNetCleanup(); #endif return; } if ( ( LOBYTE( wsa_data.wVersion ) != 2 ) || ( HIBYTE( wsa_data.wVersion ) != 2 )) { Dbg_MsgAssert( 0,( "Failed to start WinSock\n" )); WSACleanup(); #ifdef __PLAT_XBOX__ XNetCleanup(); #endif return; } #ifdef __PLAT_XBOX__ # if 0 HRESULT hr; XONLINE_STARTUP_PARAMS xosp = { 0 }; hr = XOnlineStartup( &xosp ); if( FAILED( hr )) { XOnlineCleanup(); return; } # endif #endif #else #ifdef __PLAT_NGPS__ ChangeThreadPriority( GetThreadId(), vMAIN_THREAD_PRIORITY ); m_stack_setup = false; m_options_changed = false; m_device_changed = false; m_net_drivers_loaded = false; #endif // __PLAT_NGPS__ #endif // __PLAT_WN32__ for( msg_id = 0; msg_id < 255; msg_id++ ) { SetMessageName( msg_id, "" ); SetMessageFlags( msg_id, 0 ); } SetMessageName( MSG_ID_PING_TEST, "Ping Test" ); SetMessageName( MSG_ID_PING_RESPONSE, "Ping Response" ); SetMessageName( MSG_ID_CONNECTION_REQ, "Connection Request" ); SetMessageName( MSG_ID_CONNECTION_ACCEPTED, "Connection Accepted" ); SetMessageName( MSG_ID_CONNECTION_REFUSED, "Connection Refused" ); SetMessageName( MSG_ID_CONNECTION_TERMINATED, "Connection Terminated" ); SetMessageName( MSG_ID_SEQUENCED, "Sequenced Message" ); SetMessageName( MSG_ID_ACK, "Ack" ); SetMessageName( MSG_ID_FIND_SERVER, "Find Server" ); SetMessageName( MSG_ID_SERVER_RESPONSE, "Server Find Response" ); SetMessageName( MSG_ID_TIMESTAMP, "Timestamp" ); SetMessageName( MSG_ID_ALIAS, "New Alias" ); SetMessageName( MSG_ID_DISCONN_REQ, "Disconn Request" ); SetMessageName( MSG_ID_DISCONN_ACCEPTED, "Disconn Accepted" ); SetMessageFlags( MSG_ID_TIMESTAMP, mMSG_SIZE_UNKNOWN ); SetMessageFlags( MSG_ID_ACK, mMSG_SIZE_UNKNOWN ); sprintf( m_local_ip, "" ); sprintf( m_gateway, DEFAULT_SNPS2_GATEWAY ); sprintf( m_subnet, DEFAULT_SNPS2_SUB_MSK ); m_num_apps = 0; m_conn_type = vCONN_TYPE_NONE; m_use_dhcp = false; m_online = false; m_use_dialup_auth = false; m_last_error = vRES_SUCCESS; m_modem_state = vMODEM_STATE_DISCONNECTED; m_modem_err = 0; for( i = 0; i < 3; i++ ) { m_dns_servers[i][0] = '\0'; } #ifdef __PLAT_NGPS__ m_bandwidth = 4200; // Default to a 33.6kbps modem's approximate payload threshold (i.e. including packet overhead) #else m_bandwidth = 400000; // On Xbox, just assume broadband #endif } /******************************************************************/ /* */ /* */ /******************************************************************/ Manager::~Manager( void ) { #if( defined ( __PLAT_WN32__ ) || defined ( __PLAT_XBOX__ )) WSACleanup(); #endif #ifdef __PLAT_XBOX__ XNetCleanup(); # if 0 XOnlineCleanup(); # endif #endif #ifdef __PLAT_NGC__ SOCleanup(); #endif #ifdef __PLAT_NGPS__ sn_int32 stack_state, result; if( m_stack_setup ) { // Stop the stack result = sn_stack_state(SN_STACK_STATE_STOP, &stack_state ); Dbg_MsgAssert( result == 0,( "EE:sn_stack_sate() failed %d\n", result )); // De-Register this thread with the socket API Dbg_Printf( "EE:Calling sockAPIderegthr()\n" ); sockAPIderegthr(); } #endif // __PLAY_NGPS__ } /******************************************************************/ /* */ /* */ /******************************************************************/ #ifdef __PLAT_NGPS__ void Manager::conn_modem_state_callback( sn_int32 modem_state ) { Net::Manager * net_man = Net::Manager::Instance(); Dbg_Printf(" Modem state %d = %s\n", modem_state, sntc_str_modem_state( modem_state )); switch( modem_state ) { case SN_MODEM_READY: case SN_MODEM_DIALING: net_man->SetModemState( vMODEM_STATE_DIALING ); // If we're using PAP/CHAP, clear the login script. We do it here instead of before // sntc_connect_modem() because that call resets to the default login script. if( net_man->ShouldUseDialupAuthentication()) { sndev_set_null_scrpt_type clr; int result; clr.reserved = 0; result = sndev_set_options(0, SN_DEV_SET_NULL_SCRPT, &clr, sizeof(clr)); Dbg_Printf( "EE:sndev_set_options(clr) returned %d\n", result ); } Dbg_Printf( "Setting modem state to modem state dialing\n" ); break; case SN_MODEM_LOGIN: Dbg_Printf( "Setting modem state to modem state connected\n" ); net_man->SetModemState( vMODEM_STATE_CONNECTED ); break; case SN_MODEM_PPP_UP: Dbg_Printf( "Setting modem state to modem state logged in\n" ); net_man->SetModemState( vMODEM_STATE_LOGGED_IN ); break; default: return; }; } /******************************************************************/ /* */ /* */ /******************************************************************/ void Manager::disconn_modem_state_callback( sn_int32 modem_state ) { Net::Manager * net_man = Net::Manager::Instance(); Dbg_Printf(" Modem state = %s\n", sntc_str_modem_state( modem_state )); switch( modem_state ) { case SN_MODEM_HANGINGUP: net_man->SetModemState( vMODEM_STATE_HANGING_UP ); break; default: return; }; } #endif /******************************************************************/ /* */ /* */ /******************************************************************/ bool Manager::NetworkEnvironmentSetup( void ) { #ifdef __PLAT_NGPS__ return initialize_ps2(); #endif #ifdef __PLAT_NGC__ return initialize_ngc(); #endif return true; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool Manager::NeedToTestNetworkEnvironment( void ) { #ifdef __PLAT_NGPS__ if( m_net_drivers_loaded && m_device_changed ) { return true; } if( !m_stack_setup || m_options_changed ) { return true; } #endif return false; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool Manager::ConnectToInternet( void ) { #ifdef __PLAT_NGPS__ if(( IsOnline() == false ) || m_options_changed ) { if( GetConnectionType() == vCONN_TYPE_ETHERNET ) { m_online = true; } else if(( GetConnectionType() == vCONN_TYPE_MODEM ) || ( GetConnectionType() == vCONN_TYPE_PPPOE )) { int result, device_type; int modem_state; s_cancel_dialup_conn = false; result = sndev_get_attached(0, &device_type, NULL, NULL); // Check that the above function call worked ok if( result != 0 ) { SetModemState( vMODEM_STATE_ERROR ); m_modem_err = SNTC_ERR_NOMODEM; return false; } // Check that there is a compatible modem attached if( device_type != SN_DEV_TYPE_USB_MODEM ) { SetModemState( vMODEM_STATE_ERROR ); m_modem_err = SNTC_ERR_NOMODEM; return false; } result = snmdm_get_state( &modem_state ); // Check that the above function call worked ok if( result != 0 ) { SetModemState( vMODEM_STATE_ERROR ); m_modem_err = SNTC_ERR_NOMODEM; return false; } // Make sure that the modem is ready to dial, if not reset it if( ( modem_state != SN_MODEM_READY ) && ( modem_state != SN_MODEM_READY_AUTOANS )) { sn_char* err_msg_ptr; Dbg_Printf( "EE:Calling sntc_reset_modem()\n" ); // Attempt to reset the modem result = sntc_reset_modem( vMODEM_RESET_TIMEOUT, // timeout_secs disconn_modem_state_callback, // callback &err_msg_ptr ); // error_message // If failed to reset the modem, then the result, and // error_message will have been set up by sntc_reset_modem. if( result != 0 ) { SetModemState( vMODEM_STATE_ERROR ); m_modem_err = SNTC_ERR_NOMODEM; return false; } } { struct SemaParam params; params.initCount = 1; params.maxCount = 10; s_conn_semaphore = CreateSema( ¶ms ); // Clear the modem state before we start SetModemState( -1 ); m_modem_thread_data.m_pEntry = threaded_modem_conn; m_modem_thread_data.m_iInitialPriority = vSOCKET_THREAD_PRIORITY; m_modem_thread_data.m_pStackBase = m_modem_thread_stack; m_modem_thread_data.m_iStackSize = vMODEM_THREAD_STACK_SIZE; m_modem_thread_data.m_utid = 0x150;//vBASE_SOCKET_THREAD_ID + NumApps(); Thread::CreateThread( &m_modem_thread_data ); m_modem_thread_id = m_modem_thread_data.m_osId; StartThread( m_modem_thread_id, this ); } } } #else m_online = true; #endif return m_online; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool Manager::DisconnectFromInternet( void ) { #ifdef __PLAT_NGPS__ if( m_conn_type == vCONN_TYPE_ETHERNET ) { m_online = false; } else if( ( m_conn_type == vCONN_TYPE_MODEM ) || ( m_conn_type == vCONN_TYPE_PPPOE )) { // Just in case the modem thread is running, stop it s_cancel_dialup_conn = true; WaitSema( s_conn_semaphore ); DeleteSema( s_conn_semaphore ); TerminateThread( m_modem_thread_id ); DeleteThread( m_modem_thread_id ); SetModemState( vMODEM_STATE_DISCONNECTING ); m_modem_err = 0; m_modem_thread_data.m_pEntry = threaded_modem_disconn; m_modem_thread_data.m_iInitialPriority = vSOCKET_THREAD_PRIORITY; m_modem_thread_data.m_pStackBase = m_modem_thread_stack; m_modem_thread_data.m_iStackSize = vMODEM_THREAD_STACK_SIZE; m_modem_thread_data.m_utid = 0x14F;//vBASE_SOCKET_THREAD_ID + NumApps(); Thread::CreateThread( &m_modem_thread_data ); m_modem_thread_id = m_modem_thread_data.m_osId; StartThread( m_modem_thread_id, this ); } #else m_online = false; #endif return ( m_online == false ); } /******************************************************************/ /* */ /* */ /******************************************************************/ int Manager::GetModemBaudRate( void ) { return m_modem_baud_rate; } /******************************************************************/ /* */ /* */ /******************************************************************/ void Manager::SetBandwidth( int bytes_per_sec ) { m_bandwidth = bytes_per_sec; } /******************************************************************/ /* */ /* */ /******************************************************************/ int Manager::GetBandwidth( void ) { return m_bandwidth; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool Manager::IsOnline( void ) { #ifdef __PLAT_NGPS__ if( ( GetConnectionType() == vCONN_TYPE_MODEM ) || ( GetConnectionType() == vCONN_TYPE_PPPOE )) { int modem_state; m_online = false; if( snmdm_get_state( &modem_state ) == 0 ) { if( modem_state == SN_MODEM_PPP_UP ) { m_online = true; } } } #endif// __PLAT_NGPS__ return m_online; } /******************************************************************/ /* */ /* */ /******************************************************************/ void Manager::SetISPPhoneNumber( char* phone_no ) { Dbg_Assert( phone_no ); strcpy( m_isp_phone_no, phone_no ); } /******************************************************************/ /* */ /* */ /******************************************************************/ void Manager::SetISPLogin( char* login ) { Dbg_Assert( login ); strcpy( m_isp_user_name, login ); } /******************************************************************/ /* */ /* */ /******************************************************************/ void Manager::SetISPPassword( char* password ) { Dbg_Assert( password ); strcpy( m_isp_password, password ); } /******************************************************************/ /* */ /* */ /******************************************************************/ void Manager::SetGateway( char* ip ) { if( strcmp( ip, m_gateway )) { strcpy( m_gateway, ip ); #ifdef __PLAT_NGPS__ m_options_changed = true; #endif // __PLAT_NGC__ } } /******************************************************************/ /* */ /* */ /******************************************************************/ void Manager::SetSubnetMask( char* ip ) { if( strcmp( ip, m_subnet )) { strcpy( m_subnet, ip ); #ifdef __PLAT_NGPS__ m_options_changed = true; #endif // __PLAT_NGC__ } } /******************************************************************/ /* */ /* */ /******************************************************************/ void Manager::SetPublicIP( unsigned int ip ) { m_public_ip = ip; } /******************************************************************/ /* */ /* */ /******************************************************************/ void Manager::SetLocalIP( char* ip ) { if( strcmp( ip, m_local_ip )) { strcpy( m_local_ip, ip ); #ifdef __PLAT_NGPS__ m_options_changed = true; #endif // __PLAT_NGC__ } } /******************************************************************/ /* */ /* */ /******************************************************************/ void Manager::SetConnectionType( ConnType conn_type ) { if( m_conn_type != conn_type ) { #ifdef __PLAT_NGPS__ if( m_conn_type != vCONN_TYPE_NONE ) { m_device_changed = true; } #endif // __PLAT_NGC__ m_conn_type = conn_type; // Some default values for bandwidth limiting switch( m_conn_type ) { case vCONN_TYPE_MODEM: SetBandwidth( 4200 ); break; case vCONN_TYPE_ETHERNET: SetBandwidth( 400000 ); break; case vCONN_TYPE_PPPOE: SetBandwidth( 300000 ); break; default: break; } } } /******************************************************************/ /* */ /* */ /******************************************************************/ void Manager::SetDeviceType( DeviceType dev_type ) { if( m_device_type != dev_type ) { #ifdef __PLAT_NGPS__ if( m_device_type != vDEV_TYPE_NONE ) { m_device_changed = true; } #endif // __PLAT_NGC__ m_device_type = dev_type; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void Manager::SetDHCP( bool use_dhcp ) { if( m_use_dhcp != use_dhcp ) { m_use_dhcp = use_dhcp; #ifdef __PLAT_NGPS__ m_options_changed = true; #endif // __PLAT_NGC__ } } /******************************************************************/ /* */ /* */ /******************************************************************/ void Manager::SetDialupAuthentication( bool authenticate ) { m_use_dialup_auth = authenticate; } /******************************************************************/ /* */ /* */ /******************************************************************/ void Manager::SetDNSServer( int index, char* ip ) { Dbg_Assert(( index >= 0 ) && ( index < 3 )); Dbg_Assert( ip ); if( strcmp( ip, m_dns_servers[index] )) { strcpy( m_dns_servers[index], ip ); #ifdef __PLAT_NGPS__ m_options_changed = true; #endif // __PLAT_NGC__ } } /******************************************************************/ /* */ /* */ /******************************************************************/ void Manager::SetHostName( char* host ) { // Either they pass us NULL or they pass us a value less than 32 chars long Dbg_Assert( !host || ( strlen( host ) < 32 )); if( host == NULL ) { m_host_name[0] = '\0'; } strcpy( m_host_name, host ); } /******************************************************************/ /* */ /* */ /******************************************************************/ void Manager::SetDomainName( char* domain ) { // Either they pass us NULL or they pass us a value less than 32 chars long Dbg_Assert( !domain || ( strlen( domain ) < 32 )); if( domain == NULL ) { m_domain_name[0] = '\0'; } strcpy( m_domain_name, domain ); } /******************************************************************/ /* */ /* */ /******************************************************************/ char* Manager::GetDNSServer( int index ) { Dbg_Assert(( index >= 0 ) && ( index < 3 )); return m_dns_servers[index]; } /******************************************************************/ /* */ /* */ /******************************************************************/ char* Manager::GetISPPhoneNumber( void ) { if( GetConnectionType() == vCONN_TYPE_PPPOE ) { return ""; } return m_isp_phone_no; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool Manager::ShouldUseDHCP( void ) { if(( GetConnectionType() == vCONN_TYPE_PPPOE ) || ( GetConnectionType() == vCONN_TYPE_MODEM )) { return false; } return m_use_dhcp; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool Manager::ShouldUseDialupAuthentication( void ) { if( GetConnectionType() == vCONN_TYPE_PPPOE ) { return true; } return m_use_dialup_auth; } /******************************************************************/ /* */ /* */ /******************************************************************/ char* Manager::GetGateway( void ) { return m_gateway; } /******************************************************************/ /* */ /* */ /******************************************************************/ char* Manager::GetSubnetMask( void ) { return m_subnet; } /******************************************************************/ /* */ /* */ /******************************************************************/ char* Manager::GetHostName( void ) { return m_host_name; } /******************************************************************/ /* */ /* */ /******************************************************************/ char* Manager::GetDomainName( void ) { return m_domain_name; } /******************************************************************/ /* */ /* */ /******************************************************************/ unsigned int Manager::GetPublicIP( void ) { if( m_public_ip == 0 ) { return inet_addr( m_local_ip ); } return m_public_ip; } /******************************************************************/ /* */ /* */ /******************************************************************/ char* Manager::GetLocalIP( void ) { #if defined( __PLAT_NGPS__ ) || defined( __PLAT_XBOX__ ) || defined( __PLAT_NGC__ ) return m_local_ip; #else struct hostent *host, *local_host; struct in_addr address; char *ip_str; int ip; if(( local_host = gethostbyname( "localhost" ))) { if(( host = gethostbyname( local_host->h_name ))) { ip = *(unsigned long *) host->h_addr_list[0]; address.s_addr = ip; ip_str = inet_ntoa( address ); return ip_str; } else { ip = *(unsigned long *) local_host->h_addr_list[0]; address.s_addr = ip; ip_str = inet_ntoa( address ); return ip_str; } } return ""; #endif } /******************************************************************/ /* */ /* */ /******************************************************************/ ConnType Manager::GetConnectionType( void ) { return m_conn_type; } /******************************************************************/ /* */ /* */ /******************************************************************/ DeviceType Manager::GetDeviceType( void ) { #ifdef __PLAT_XBOX__ return vDEV_TYPE_USB_ETHERNET; #else return m_device_type; #endif } /******************************************************************/ /* */ /* */ /******************************************************************/ void Manager::SetError( int error ) { m_last_error = error; } /******************************************************************/ /* */ /* */ /******************************************************************/ int Manager::GetLastError( void ) { return m_last_error; } /******************************************************************/ /* Get the name associated with a message id */ /* */ /******************************************************************/ char* Manager::GetMessageName( unsigned char msg_id ) { #ifdef NET_DEBUG_MESSAGES return m_message_names[ msg_id ]; #else return ""; #endif } /******************************************************************/ /* Associate a text name with a message id for debugging purposes */ /* */ /******************************************************************/ void Manager::SetMessageName( unsigned char msg_id, char* msg_name ) { #ifdef NET_DEBUG_MESSAGES Dbg_Assert( msg_name ); strncpy( m_message_names[ msg_id ], msg_name, vMAX_MSG_NAME_LEN - 1 ); m_message_names[msg_id][vMAX_MSG_NAME_LEN - 1] = '\0'; #endif } /******************************************************************/ /* */ /* */ /******************************************************************/ char Manager::GetMessageFlags( unsigned char msg_id ) { return m_message_flags[ msg_id ]; } /******************************************************************/ /* */ /* */ /******************************************************************/ void Manager::SetMessageFlags( unsigned char msg_id, char flags ) { m_message_flags[ msg_id ] = flags; } /******************************************************************/ /* */ /* */ /******************************************************************/ int Manager::GetModemState( void ) { return m_modem_state; } /******************************************************************/ /* */ /* */ /******************************************************************/ void Manager::SetModemState( int state ) { m_modem_state = state; } /******************************************************************/ /* */ /* */ /******************************************************************/ int Manager::GetModemError( void ) { return m_modem_err; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool Manager::CanChangeDevices( void ) { #ifdef __PLAT_NGPS__ return !m_net_drivers_loaded; #else return true; #endif } /******************************************************************/ /* */ /* */ /******************************************************************/ MsgLink::MsgLink( QueuedMsg *msg ) : Lst::Node< MsgLink > ( this ), m_QMsg( msg ), m_SendTime( 0 ) { } /******************************************************************/ /* */ /* */ /******************************************************************/ MsgImpLink::MsgImpLink( QueuedMsg *msg ) : Lst::Node< MsgImpLink > ( this ), m_QMsg( msg ), m_SendTime( 0 ) { m_NumResends = 0; } /******************************************************************/ /* */ /* */ /******************************************************************/ MsgSeqLink::MsgSeqLink( QueuedMsgSeq *msg ) : Lst::Node< MsgSeqLink > ( this ), m_StreamMessage( 0 ), m_SendTime( 0 ), m_QMsg( msg ) { m_NumResends = 0; } /******************************************************************/ /* */ /* */ /******************************************************************/ StreamLink::StreamLink( StreamDesc* desc ) : Lst::Node< StreamLink > ( this ), m_Desc ( desc ) { } /******************************************************************/ /* */ /* */ /******************************************************************/ StreamDesc::StreamDesc( void ) : m_Size( 0 ), m_Data( NULL ), m_DataPtr( NULL ), m_GroupId( 0 ), m_SendInPlace( false ) { } /******************************************************************/ /* */ /* */ /******************************************************************/ StreamDesc::~StreamDesc( void ) { if( m_Data && !m_SendInPlace ) { delete [] m_Data; } } /******************************************************************/ /* */ /* */ /******************************************************************/ MsgDesc::MsgDesc( void ) : m_Id( 0 ), m_StreamMessage( 0 ), m_Length( 0 ), m_Data( 0 ), m_Priority( NORMAL_PRIORITY ), m_Queue( QUEUE_DEFAULT ), m_GroupId( GROUP_ID_DEFAULT ), m_Singular( false ), m_Delay( 0 ), m_ForcedSequenceId( 0 ) { } /******************************************************************/ /* */ /* */ /******************************************************************/ QueuedMsg::QueuedMsg( unsigned char msg_id, unsigned short msg_len, void* data ) { m_Data = NULL; if( msg_len > 0 ) { m_Data = new char[ msg_len ]; memcpy( m_Data, data, msg_len ); } m_MsgId = msg_id; m_MsgLength = msg_len; #ifdef __PLAT_NGPS__ Dbg_MsgAssert(Mem::SameContext(this,Mem::Manager::sHandle().NetworkHeap()),("QueuedMsg not on network heap")); #endif // __PLAT_NGPS__ } /******************************************************************/ /* */ /* */ /******************************************************************/ QueuedMsg::~QueuedMsg( void ) { if( m_Data ) { delete [] m_Data; } } /******************************************************************/ /* */ /* */ /******************************************************************/ QueuedMsgSeq::QueuedMsgSeq( unsigned char msg_id, unsigned short msg_len, void* data, unsigned char group_id ) { m_Data = NULL; if( msg_len > 0 ) { m_Data = new char[ msg_len ]; memcpy( m_Data, data, msg_len ); } m_MsgId = msg_id; m_MsgLength = msg_len; m_GroupId = group_id; #ifdef __PLAT_NGPS__ Dbg_MsgAssert(Mem::SameContext(this,Mem::Manager::sHandle().NetworkHeap()),("QueuedMsgSeq not on network heap")); #endif // __PLAT_NGPS__ } /******************************************************************/ /* */ /* */ /******************************************************************/ QueuedMsgSeq::~QueuedMsgSeq( void ) { if( m_Data ) { delete [] m_Data; } } /******************************************************************/ /* */ /* */ /******************************************************************/ BitStream::BitStream( void ) { m_data = NULL; m_bits_left = 32; m_size = 0; m_cur_val = 0; m_bits_processed = 0; } /******************************************************************/ /* */ /* */ /******************************************************************/ void BitStream::SetInputData( char* data, int size ) { m_data = (unsigned int*) data; m_start_data = m_data; m_size = size; m_bits_left = 0; m_bits_processed = 0; } /******************************************************************/ /* */ /* */ /******************************************************************/ void BitStream::SetOutputData( char* data, int size ) { m_data = (unsigned int*) data; m_start_data = m_data; m_size = size; m_bits_left = 32; m_bits_processed = 0; } /******************************************************************/ /* */ /* */ /******************************************************************/ int BitStream::GetByteLength( void ) { return (( m_bits_processed + 7 ) >> 3 ); } /******************************************************************/ /* */ /* */ /******************************************************************/ void BitStream::WriteValue( int value, int num_bits ) { m_bits_processed += num_bits; // If we cannot fit all bits into our current int, we'll have to span it over // two ints if( m_bits_left < num_bits ) { // Write out the first portion, then advance to the next int // First clear all top (unwritten) bits m_cur_val &= ( 1 << ( 32 - m_bits_left )) - 1; // Now write them (without having to mask low bits off) m_cur_val |= value << ( 32 - m_bits_left ); num_bits -= m_bits_left; value >>= m_bits_left; memcpy( m_data, &m_cur_val, sizeof( unsigned int )); m_data++; m_cur_val = 0; m_bits_left = 32; } // First clear all top (unwritten) bits m_cur_val &= ( 1 << ( 32 - m_bits_left )) - 1; // Now write them (without having to mask low bits off) m_cur_val |= value << ( 32 - m_bits_left ); m_bits_left -= num_bits; // Flush bits if full if( m_bits_left == 0 ) { memcpy((char*) m_data, (char*) &m_cur_val, sizeof( unsigned int )); m_data++; m_cur_val = 0; m_bits_left = 32; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void BitStream::WriteFloatValue( float value ) { WriteValue( *(int*) &value, sizeof( float ) * 8 ); } /******************************************************************/ /* */ /* */ /******************************************************************/ void BitStream::Flush( void ) { // Only flush if we have bits to flush if( m_bits_left != 32) { memcpy( m_data, &m_cur_val, sizeof( unsigned int )); m_data++; m_cur_val = 0; m_bits_left = 32; } } /******************************************************************/ /* */ /* */ /******************************************************************/ float BitStream::ReadFloatValue( void ) { float res; int num_bits; num_bits = 32; m_bits_processed += num_bits; // If we're all out of bits (like at start), read a full word if( m_bits_left == 0 ) { memcpy( &m_cur_val, m_data, sizeof( unsigned int )); m_data++; m_bits_left = 32; } // Do we hold all bits requested? if( m_bits_left >= num_bits ) { // Yes, easy peasy case m_bits_left -= num_bits; if( num_bits == 32 ) { memcpy( &res, &m_cur_val, sizeof( float )); } else { unsigned int int_val; int_val = m_cur_val & ((1 << num_bits) - 1); memcpy( &res, &int_val, sizeof( float )); } m_cur_val >>= num_bits; } else { unsigned int int_val; // Nope, grab those we have and fetch more from stream int_val = m_cur_val & (( 1 << m_bits_left ) - 1); num_bits -= m_bits_left; memcpy( &m_cur_val, m_data, sizeof( unsigned int )); m_data++; int_val |= ( m_cur_val & (( 1 << num_bits ) - 1)) << m_bits_left; m_cur_val >>= num_bits; m_bits_left = 32 - num_bits; memcpy( &res, &int_val, sizeof( float )); } return res; } /******************************************************************/ /* */ /* */ /******************************************************************/ unsigned int BitStream::ReadUnsignedValue( int num_bits ) { unsigned long res; Dbg_Assert(( num_bits >= 0 ) && ( num_bits <= 32 )); m_bits_processed += num_bits; // If we're all out of bits (like at start), read a full word if( m_bits_left == 0 ) { memcpy( &m_cur_val, m_data, sizeof( unsigned int )); m_data++; m_bits_left = 32; } // Do we hold all bits requested? if( m_bits_left >= num_bits ) { // Yes, easy peasy case m_bits_left -= num_bits; if( num_bits == 32 ) { res = m_cur_val; } else { res = m_cur_val & ((1 << num_bits) - 1); } m_cur_val >>= num_bits; } else { // Nope, grab those we have and fetch more from stream res = m_cur_val & (( 1 << m_bits_left ) - 1); num_bits -= m_bits_left; memcpy( &m_cur_val, m_data, sizeof( unsigned int )); m_data++; res |= ( m_cur_val & (( 1 << num_bits ) - 1)) << m_bits_left; m_cur_val >>= num_bits; m_bits_left = 32 - num_bits; } return res; } /******************************************************************/ /* */ /* */ /******************************************************************/ int BitStream::ReadSignedValue( int num_bits ) { long res; Dbg_Assert(( num_bits >= 0 ) && ( num_bits <= 32 )); // Cheasy call to that other function for simplicity res = ReadUnsignedValue( num_bits ); // Sign extend result if sign bit set if( res & ( 1 << ( num_bits - 1 ))) { res |= ~(( 1 << num_bits ) - 1 ); } return res; } /******************************************************************/ /* */ /* */ /******************************************************************/ } // namespace Net