netstat.c

Go to the documentation of this file.
00001 
00025 #include <string.h>
00026 #include <stdlib.h>
00027 #include "color.h"
00028 #include "genconmac.h"
00029 #include "hostlookup.h"
00030 #include "netstat.h"
00031 #include "text.h"
00032 #include "timesync.h"
00033 #include "net.h"
00034 #ifndef WIN32
00035 #include <sys/types.h>
00036 #include <sys/socket.h>
00037 #include <arpa/inet.h>
00038 #endif
00039 
00040 char statHost[MAX_HOST_LEN];
00041 
00047 struct NetStatData_t {
00051     int prevNetStat;
00056     int prevSyncStat;
00060     Bool gotHost;
00061 };
00062 
00063 typedef struct NetStatData_t  NetStatData;
00064 
00071 #define netdat  ((NetStatData*)(item->data))
00072 
00073 Bool NetStatInit(MenuItem *item) {
00074     // allocate memory for the persistant state
00075     if ((item->data = malloc(sizeof(NetStatData))) == NULL) {
00076         // failed
00077         return FALSE;
00078     }
00079     netdat->prevNetStat = netdat->prevSyncStat = -1;
00080     // setup the menu item fields
00081     item->minWidth = 480;
00082     item->minHeight = (textItems[TEXTITEM_FIREOPT].loc.h << 1) + 2;
00083     item->focus = NetStatFocus;
00084     item->input = NetStatInput;
00085     item->update = NetStatUpdate;
00086     item->active = TRUE;
00087     // put the item containing the network status message into a layer
00088     if (textItems[TEXTITEM_NETSTAT].renderer == NULL) {
00089         // the text item will be initialized later with a call to
00090         // TextRenderString() before it is drawn
00091         textItems[TEXTITEM_NETSTAT].renderer = (ItemRenderer)1;
00092     }
00093     AddRenderItem(&(textItems[TEXTITEM_NETSTAT]), LAYER_TEXT);
00094     if (textItems[TEXTITEM_NETOPTS].renderer == NULL) {
00095         textItems[TEXTITEM_NETOPTS].renderer = (ItemRenderer)1;
00096     }
00097     AddRenderItem(&(textItems[TEXTITEM_NETOPTS]), LAYER_TEXT);
00098     // TEXTITEM_FIREOPT is added by the text system for the menu state because
00099     // it is a constant string.
00100     return TRUE;
00101 }
00102 
00103 void NetStatUninit(MenuItem *item) {
00104     free(netdat);
00105 }
00106 
00107 extern SocketAddr outgoingAddr;
00108 
00116 static void RenderLocalAddr(MenuItem *item) {
00117     // render the address
00118     TextRenderString(&(textItems[TEXTITEM_NETOPTS]), FONT_SCORE, 0,
00119     colorFmtInd[COLOR_TEXT], strings[STRING_NETADDR], localhostAddrStr);
00120     // place it
00121     textItems[TEXTITEM_NETOPTS].loc.x = item->region.x +
00122     ((item->region.w - textItems[TEXTITEM_NETOPTS].loc.w) >> 1);
00123     textItems[TEXTITEM_NETOPTS].loc.y = item->region.y +
00124     textItems[TEXTITEM_NETOPTS].loc.h + 2;
00125 }
00126 
00133 static void RenderTSync(MenuItem *item) {
00134     // render the address
00135     TextRenderString(&(textItems[TEXTITEM_NETOPTS]), FONT_SCORE, 0,
00136     colorFmtInd[COLOR_TEXT], strings[STRING_NETSYNC]);
00137     // place it
00138     textItems[TEXTITEM_NETOPTS].loc.x = item->region.x +
00139     ((item->region.w - textItems[TEXTITEM_NETOPTS].loc.w) >> 1);
00140     textItems[TEXTITEM_NETOPTS].loc.y = item->region.y +
00141     textItems[TEXTITEM_NETOPTS].loc.h + 2;
00142 }
00143 
00150 static void RenderLatency(MenuItem *item) {
00151     // render the address
00152     TextRenderString(&(textItems[TEXTITEM_NETOPTS]), FONT_SCORE, 0,
00153     colorFmtInd[COLOR_TEXT], strings[STRING_NETLAT], timeSyncResults.latency);
00154     // place it
00155     textItems[TEXTITEM_NETOPTS].loc.x = item->region.x +
00156     ((item->region.w - textItems[TEXTITEM_NETOPTS].loc.w) >> 1);
00157     textItems[TEXTITEM_NETOPTS].loc.y = item->region.y +
00158     textItems[TEXTITEM_NETOPTS].loc.h + 2;
00159 }
00160 
00161 int NetStatUpdate(MenuItem *item) { 
00162     // update the data with the latest information from the server
00163     // see if the visible components need to be moved
00164     if (!item->isPlaced) {
00165         // set the placed flag
00166         item->isPlaced = TRUE;
00167         // set the host flag
00168         netdat->gotHost = FALSE;
00169         
00170         // Move the components to the proper place.
00171         // Place the fire for options prompt
00172         textItems[TEXTITEM_FIREOPT].loc.x = item->region.x +
00173         ((item->region.w - textItems[TEXTITEM_FIREOPT].loc.w) >> 1);
00174         textItems[TEXTITEM_FIREOPT].loc.y = item->region.y +
00175         textItems[TEXTITEM_FIREOPT].loc.h + 2;
00176         
00177         // check for a found address
00178         if (localhostAddrStr[0]) {
00179             // render the address
00180             RenderLocalAddr(item);
00181         }
00182         
00183         // see if the options prompt should be visible now
00184         if (item->hasFocus) {
00185             // display it at its new location
00186             PlaceRenderItem(&(textItems[TEXTITEM_FIREOPT]));
00187         }
00188         else if (localhostAddrStr[0]) {
00189             // diplay the game options
00190             PlaceRenderItem(&(textItems[TEXTITEM_NETOPTS]));
00191         }
00192         goto NetStatUpdate_statStr;
00193     }
00194     // see if the network state has changed since the text was rendered
00195     if ((netdat->prevNetStat != networkState) ||
00196     (!netdat->gotHost && (LookupResult(NULL, NULL) != 0))) {
00197         rtsa_char const     *str;
00198         #ifndef WIN32
00199         char addrstr[INET6_ADDRSTRLEN];
00200         #endif
00201         NetStatUpdate_statStr:
00202         // make the current network state the previous one
00203         netdat->prevNetStat = networkState;
00204         // check for need to lookup name of remote server
00205         if ((networkState == NETSTATE_CONNECTING) ||
00206         (networkState == NETSTATE_RCVCFG) ||
00207         (networkState == NETSTATE_CLIENT) ||
00208         (networkState == NETSTATE_SRVDENY)) {
00209             // if there is no host name and an address can be put into a string
00210             if ((statHost[0] == 0) &&
00211             #ifdef WIN32
00212             // use the older IPv4 functions
00213             ((str = (rtsa_char*)inet_ntoa(outgoingAddr.ipv4.sin_addr)) != NULL)) {
00214                 // do nothing to maintain the same logic as on other systems
00215             }
00216             #else
00217             (inet_ntop(outgoingAddr.addr.sa_family,
00218             (outgoingAddr.addr.sa_family == AF_INET) ?
00219             (void*)&(outgoingAddr.ipv4.sin_addr) : 
00220             (void*)&(outgoingAddr.ipv6.sin6_addr),
00221             addrstr, INET6_ADDRSTRLEN) != NULL)) {
00222                 // use the address
00223                 str = (rtsa_char*)addrstr;
00224             }
00225             #endif
00226             else {
00227                 // use the host name
00228                 str = (rtsa_char*)statHost;
00229                 netdat->gotHost = TRUE;
00230             }
00231         }
00232         else if ((netdat->prevNetStat >= NETSTATE_SEARCHERR) &&
00233         (netdat->prevNetStat <= NETSTATE_CONERR)) {
00234             str = GetNetErrorString(netError);
00235         }
00236         else {
00237             str = (rtsa_char*)localhostName;
00238         }
00239         // render status text
00240         TextRenderString(&(textItems[TEXTITEM_NETSTAT]), FONT_SCORE, 0,
00241         colorFmtInd[COLOR_TEXT],
00242         strings[STRING_NETLOOKING + netdat->prevNetStat - 1], str);
00243         // place the text
00244         textItems[TEXTITEM_NETSTAT].loc.x = item->region.x + 2;
00245         textItems[TEXTITEM_NETSTAT].loc.y = item->region.y;
00246         PlaceRenderItem(&(textItems[TEXTITEM_NETSTAT]));
00247         
00248         if (networkState == NETSTATE_DISCONN) {
00249             ClearRenderItem(&(textItems[TEXTITEM_NETOPTS]));
00250         }
00251     }
00252     // check for a change in the time sync state
00253     if (netdat->prevSyncStat != timeSyncState) {
00254         // store the current state
00255         netdat->prevSyncStat = timeSyncState;
00256         // client side display
00257         if ((networkState == NETSTATE_RCVCFG) ||
00258         (networkState == NETSTATE_CLIENT)) {
00259             // if time sync is in progress . . .
00260             switch (timeSyncState) {
00261                 case TIMESYNC_INPROG:
00262                     RenderTSync(item);
00263                     break;
00264                 case TIMESYNC_FINISHED:
00265                 case TIMESYNC_POOR:
00266                     RenderLatency(item);
00267                     break;
00268                 default:
00269                     RenderLocalAddr(item);
00270             }
00271             // if the text is visible
00272             if (!item->hasFocus) {
00273                 PlaceRenderItem(&(textItems[TEXTITEM_NETOPTS]));
00274             }
00275         }
00276         // others
00277         else if (localhostAddrStr[0]) {
00278             RenderLocalAddr(item);
00279             // if the text is visible
00280             if (!item->hasFocus) {
00281                 PlaceRenderItem(&(textItems[TEXTITEM_NETOPTS]));
00282             }
00283         }
00284     }
00285     return 0;
00286 }
00287 
00288 void NetStatFocus(MenuItem *item) {
00289     // check for focus
00290     if (item->hasFocus) {
00291         // show the fire for options prompt
00292         PlaceRenderItem(&(textItems[TEXTITEM_FIREOPT]));
00293         if (localhostAddrStr[0] || (timeSyncState &&
00294         (networkState == NETSTATE_CLIENT))) {
00295             // remove the game options
00296             ClearRenderItem(&(textItems[TEXTITEM_NETOPTS]));
00297         }
00298     }
00299     else {
00300         // remove the fire for options prompt
00301         ClearRenderItem(&(textItems[TEXTITEM_FIREOPT]));
00302         if ((networkState != NETSTATE_DISCONN) && (localhostAddrStr[0] ||
00303         (timeSyncState && (networkState == NETSTATE_CLIENT)))) {
00304             // show the game options
00305             PlaceRenderItem(&(textItems[TEXTITEM_NETOPTS]));
00306         }
00307     }
00308 }
00309 
00310 int NetStatInput(MenuItem *item, Uint8 *ec, rtsa_char keyval) {
00311     // nothing yet
00312     return 0;
00313 }
00314 

Generated on Mon May 28 04:41:39 2007 for Retro Tank Super Attack by  doxygen 1.5.2