From e0ece3f35bfc1156e88895da3c4f2e551d86c6a6 Mon Sep 17 00:00:00 2001 From: bgk Date: Sun, 9 Sep 2012 11:01:20 +0000 Subject: [PATCH] LINK: Continue simplifying the link init oode git-svn-id: https://svn.code.sf.net/p/vbam/code/branches/bgk-link@1127 a31d4220-a93d-0410-bf67-fe4944624d44 --- src/gba/GBALink.cpp | 418 ++++++++++++++++++-------------------- src/gba/GBALink.h | 64 +++--- src/win32/LinkOptions.cpp | 5 +- src/wx/guiinit.cpp | 196 +++++------------- 4 files changed, 296 insertions(+), 387 deletions(-) diff --git a/src/gba/GBALink.cpp b/src/gba/GBALink.cpp index 4ccfdcd0..d341046e 100644 --- a/src/gba/GBALink.cpp +++ b/src/gba/GBALink.cpp @@ -148,9 +148,13 @@ int WaitForSingleObject(sem_t *s, int t) #define UPDATE_REG(address, value) WRITE16LE(((u16 *)&ioMem[address]),value) static LinkMode gba_link_mode = LINK_DISCONNECTED; +static ConnectionState gba_connection_state = LINK_OK; LinkMode GetLinkMode() { - return gba_link_mode; + if (gba_connection_state == LINK_OK) + return gba_link_mode; + else + return LINK_DISCONNECTED; } int linktime = 0; @@ -224,11 +228,6 @@ int gbtime = 1024; int GetSIOMode(u16, u16); -void LinkClientThread(void *); -void LinkServerThread(void *); - -int StartServer(void); - u16 StartRFU(u16); void StartLink(u16 value) @@ -244,7 +243,6 @@ void StartLink(u16 value) switch (GetSIOMode(value, READ16LE(&ioMem[COMM_RCNT]))) { case MULTIPLAYER: { bool start = (value & 0x80) && !linkid && !transfer && GetLinkMode() != LINK_DISCONNECTED; - u16 si = value & 4; // clear start, seqno, si (RO on slave, start = pulse on master) value &= 0xff4b; // get current si. This way, on slaves, it is low during xfer @@ -956,13 +954,13 @@ u16 StartRFU(u16 value) } } -static bool InitIPC() { +static ConnectionState InitIPC() { linkid = 0; #if (defined __WIN32__ || defined _WIN32) if((mmf=CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(LINKDATA), LOCAL_LINK_NAME))==NULL){ systemMessage(0, N_("Error creating file mapping")); - return false; + return LINK_ERROR; } if(GetLastError() == ERROR_ALREADY_EXISTS) @@ -974,7 +972,7 @@ static bool InitIPC() { if((linkmem=(LINKDATA *)MapViewOfFile(mmf, FILE_MAP_WRITE, 0, 0, sizeof(LINKDATA)))==NULL){ CloseHandle(mmf); systemMessage(0, N_("Error mapping file")); - return false; + return LINK_ERROR; } #else if((mmf = shm_open("/" LOCAL_LINK_NAME, O_RDWR|O_CREAT|O_EXCL, 0777)) < 0) { @@ -1024,7 +1022,7 @@ static bool InitIPC() { close(mmf); #endif systemMessage(0, N_("5 or more GBAs not supported.")); - return false; + return LINK_ERROR; } if(vbaid == n) linkmem->numgbas = n + 1; @@ -1045,7 +1043,7 @@ static bool InitIPC() { CloseHandle(linksync[j]); } systemMessage(0, N_("Error opening event")); - return false; + return LINK_ERROR; } #else if((linksync[i] = sem_open(linkevent, @@ -1063,45 +1061,187 @@ static bool InitIPC() { } } systemMessage(0, N_("Error opening event")); - return false; + return LINK_ERROR; } #endif } - return true; + return LINK_OK; } ////////////////////////////////////////////////////////////////////////// // Probably from here down needs to be replaced with SFML goodness :) // tjm: what SFML goodness? SFML for network, yes, but not for IPC -bool InitLink(LinkMode mode) +ConnectionState InitLink(LinkMode mode) { // Do nothing if we are already connected if (GetLinkMode() != LINK_DISCONNECTED) { systemMessage(0, N_("Error, link already connected")); - return false; + return LINK_ERROR; } - bool initOk = true; + gba_connection_state = LINK_OK; if (mode == LINK_GAMECUBE_DOLPHIN) { JoyBusConnect(); } else if (mode == LINK_CABLE_IPC || mode == LINK_RFU_IPC) { - initOk = InitIPC(); + gba_connection_state = InitIPC(); } else if (mode == LINK_CABLE_SOCKET) { - for(i=0;i<4;i++) + linkid = 0; + + for(int i = 0; i < 4; i++) linkdata[i] = 0xffff; + + if (lanlink.server) { + lanlink.connectedSlaves = 0; + // should probably use GetPublicAddress() + //sid->ShowServerIP(sf::IPAddress::GetLocalAddress()); + + // too bad Listen() doesn't take an address as well + // then again, old code used INADDR_ANY anyway + if (!lanlink.tcpsocket.Listen(IP_LINK_PORT)) + // Note: old code closed socket & retried once on bind failure + gba_connection_state = LINK_ERROR; // FIXME: error code? + else + gba_connection_state = LINK_NEEDS_UPDATE; + } else { + lc.serverport = IP_LINK_PORT; + + if (!lc.serveraddr.IsValid()) { + gba_connection_state = LINK_ERROR; + } else { + lanlink.tcpsocket.SetBlocking(false); + sf::Socket::Status status = lanlink.tcpsocket.Connect(lc.serverport, lc.serveraddr); + + if (status == sf::Socket::Error || status == sf::Socket::Disconnected) + gba_connection_state = LINK_ERROR; + else + gba_connection_state = LINK_NEEDS_UPDATE; + } + } } // No errors, save the link mode - if (initOk) { + if (gba_connection_state != LINK_ERROR) { gba_link_mode = mode; } else { gba_link_mode = LINK_DISCONNECTED; } - return initOk; + return gba_connection_state; +} + +ConnectionState ConnectLinkUpdate(char * const message, size_t size) +{ + message[0] = '\0'; + + if (gba_connection_state != LINK_NEEDS_UPDATE) { + gba_connection_state = LINK_ERROR; + snprintf(message, size, N_("Link connection does not need updates.")); + + return LINK_ERROR; + } + + if (gba_link_mode == LINK_CABLE_SOCKET && lanlink.server) { + sf::Selector fdset; + fdset.Add(lanlink.tcpsocket); + + if (fdset.Wait(0.1) == 1) { + int nextSlave = lanlink.connectedSlaves + 1; + + sf::Socket::Status st = lanlink.tcpsocket.Accept(ls.tcpsocket[nextSlave]); + + if (st == sf::Socket::Error) { + for (int j = 1; j < nextSlave; j++) + ls.tcpsocket[j].Close(); + + snprintf(message, size, N_("Network error.")); + gba_connection_state = LINK_ERROR; + } else { + sf::Packet packet; + packet << static_cast(nextSlave) + << static_cast(lanlink.numslaves); + + ls.tcpsocket[nextSlave].Send(packet); + + snprintf(message, size, N_("Player %d connected"), nextSlave); + + lanlink.connectedSlaves++; + } + } + + if (lanlink.numslaves == lanlink.connectedSlaves) { + lanlink.connected = true; + + for (int i = 1; i <= lanlink.numslaves; i++) { + sf::Packet packet; + packet << true; + + ls.tcpsocket[i].Send(packet); + } + + snprintf(message, size, N_("All players connected")); + gba_connection_state = LINK_OK; + } + } else if (gba_link_mode == LINK_CABLE_SOCKET && !lanlink.server) { + + sf::Packet packet; + sf::Socket::Status status = lanlink.tcpsocket.Receive(packet); + + if (status == sf::Socket::Error || status == sf::Socket::Disconnected) { + snprintf(message, size, N_("Network error.")); + gba_connection_state = LINK_ERROR; + } else if (status == sf::Socket::Done) { + + if (linkid == 0) { + sf::Uint16 receivedId, receivedSlaves; + packet >> receivedId >> receivedSlaves; + + if (packet) { + linkid = receivedId; + lanlink.numslaves = receivedSlaves; + + snprintf(message, size, N_("Connected as #%d, Waiting for %d players to join"), + linkid + 1, lanlink.numslaves - linkid); + } + } else { + bool gameReady; + packet >> gameReady; + + if (packet && gameReady) { + lanlink.connected = true; + gba_connection_state = LINK_OK; + snprintf(message, size, N_("All players joined.")); + } + } + + sf::Selector fdset; + fdset.Add(lanlink.tcpsocket); + fdset.Wait(0.1); + } + } + + return gba_connection_state; +} + +void SetLinkServerHost(const char *host) { + lc.serveraddr = sf::IPAddress(host); + joybusHostAddr = sf::IPAddress(host); +} + +void GetLinkServerHost(char * const host, size_t size) { + if (host == NULL || size == 0) + return; + + host[0] = '\0'; + + if (gba_link_mode == LINK_GAMECUBE_DOLPHIN) + strncpy(host, joybusHostAddr.ToString().c_str(), size); + else if (lanlink.server) + strncpy(host, sf::IPAddress::GetLocalAddress().ToString().c_str(), size); + else + strncpy(host, lc.serveraddr.ToString().c_str(), size); } static void ReInitLink() @@ -1120,11 +1260,11 @@ static void ReInitLink() } void CloseLink(void){ - if (GetLinkMode() == LINK_DISCONNECTED) { + if (gba_link_mode == LINK_DISCONNECTED) { return; // Nothing to do } - if (GetLinkMode() == LINK_GAMECUBE_DOLPHIN) { + if (gba_link_mode == LINK_GAMECUBE_DOLPHIN) { JoyBusShutdown(); } @@ -1147,45 +1287,48 @@ void CloseLink(void){ } } } - int f = linkmem->linkflags; - f &= ~(1 << linkid); - if(f & 0xf) { - linkmem->linkflags = f; - int n = linkmem->numgbas; - for(int i = 0; i < n; i--) - if(f <= (1 << (i + 1)) - 1) { - linkmem->numgbas = i + 1; - break; - } - } - for(i=0;i<4;i++){ - if(linksync[i]!=NULL){ -#if (defined __WIN32__ || defined _WIN32) - ReleaseSemaphore(linksync[i], 1, NULL); - CloseHandle(linksync[i]); -#else - sem_close(linksync[i]); - if(!(f & 0xf)) { - linkevent[sizeof(linkevent)-2]=(char)i+'1'; - sem_unlink(linkevent); - } -#endif + if (gba_link_mode == LINK_CABLE_IPC || gba_link_mode == LINK_RFU_IPC) { + int f = linkmem->linkflags; + f &= ~(1 << linkid); + if(f & 0xf) { + linkmem->linkflags = f; + int n = linkmem->numgbas; + for(int i = 0; i < n; i--) + if(f <= (1 << (i + 1)) - 1) { + linkmem->numgbas = i + 1; + break; + } } - } -#if (defined __WIN32__ || defined _WIN32) - CloseHandle(mmf); - UnmapViewOfFile(linkmem); - // FIXME: move to caller - // (but there are no callers, so why bother?) - //regSetDwordValue("LAN", lanlink.active); + for(i=0;i<4;i++){ + if(linksync[i]!=NULL){ +#if (defined __WIN32__ || defined _WIN32) + ReleaseSemaphore(linksync[i], 1, NULL); + CloseHandle(linksync[i]); #else - if(!(f & 0xf)) - shm_unlink("/" LOCAL_LINK_NAME); - munmap(linkmem, sizeof(LINKDATA)); - close(mmf); + sem_close(linksync[i]); + if(!(f & 0xf)) { + linkevent[sizeof(linkevent)-2]=(char)i+'1'; + sem_unlink(linkevent); + } #endif + } + } +#if (defined __WIN32__ || defined _WIN32) + CloseHandle(mmf); + UnmapViewOfFile(linkmem); + + // FIXME: move to caller + // (but there are no callers, so why bother?) + //regSetDwordValue("LAN", lanlink.active); +#else + if(!(f & 0xf)) + shm_unlink("/" LOCAL_LINK_NAME); + munmap(linkmem, sizeof(LINKDATA)); + close(mmf); +#endif + } gba_link_mode = LINK_DISCONNECTED; @@ -1215,81 +1358,6 @@ lserver::lserver(void){ oncewait = false; } -bool lserver::Init(ServerInfoDisplay *sid){ - // too bad Listen() doesn't take an address as well - // then again, old code used INADDR_ANY anyway - if(!lanlink.tcpsocket.Listen(IP_LINK_PORT)) - // Note: old code closed socket & retried once on bind failure - return false; // FIXME: error code? - - if(lanlink.thread!=NULL){ - lanlink.terminate = true; - WaitForSingleObject(linksync[vbaid], 500); - lanlink.thread = NULL; - } - lanlink.terminate = false; - linkid = 0; - - // should probably use GetPublicAddress() - sid->ShowServerIP(sf::IPAddress::GetLocalAddress()); - - lanlink.thread = new sf::Thread(LinkServerThread, sid); - lanlink.thread->Launch(); - - return true; - -} - -void LinkServerThread(void *_sid){ - ServerInfoDisplay *sid = (ServerInfoDisplay *)_sid; - sf::Selector fdset; - char inbuffer[256], outbuffer[256]; - s32 *intinbuffer = (s32*)inbuffer; - u16 *u16inbuffer = (u16*)inbuffer; - s32 *intoutbuffer = (s32*)outbuffer; - u16 *u16outbuffer = (u16*)outbuffer; - - i = 0; - - while(iShowConnect(i); - } - } - sid->Ping(); - } - - lanlink.connected = true; - - sid->Connected(); - - for(i=1;i<=lanlink.numslaves;i++){ - outbuffer[0] = 4; - ls.tcpsocket[i].Send(outbuffer, 4); - } - -CloseInfoDisplay: - delete sid; - return; -} - void lserver::Send(void){ if(lanlink.type==0){ // TCP if(savedlinktime==-1){ @@ -1388,92 +1456,6 @@ lclient::lclient(void){ return; } -bool lclient::Init(sf::IPAddress addr, ClientInfoDisplay *cid){ - serveraddr = addr; - serverport = IP_LINK_PORT; - lanlink.tcpsocket.SetBlocking(false); - - if(lanlink.thread!=NULL){ - lanlink.terminate = true; - WaitForSingleObject(linksync[vbaid], 500); - lanlink.thread = NULL; - } - - cid->ConnectStart(addr); - lanlink.terminate = false; - lanlink.thread = new sf::Thread(LinkClientThread, cid); - lanlink.thread->Launch(); - return true; -} - -void LinkClientThread(void *_cid){ - ClientInfoDisplay *cid = (ClientInfoDisplay *)_cid; - sf::Selector fdset; - int numbytes; - char inbuffer[16]; - u16 *u16inbuffer = (u16*)inbuffer; - unsigned long block = 0; - - while(lanlink.tcpsocket.Connect(lc.serverport, lc.serveraddr) != sf::Socket::Done) { - // stupid SFML has no way of giving what sort of error occurred - // so we'll just have to do a retry loop, I guess. - cid->Ping(); - if(lanlink.terminate) - goto CloseInfoDisplay; - // old code had broken sleep on socket, which isn't - // even connected yet - // corrected sleep on socket worked, but this is more sane - // and probably less portable... works with mingw32 at least -#if (defined __WIN32__ || defined _WIN32) - Sleep(100); // in milliseconds -#else - usleep(100000); // in microseconds -#endif - } - - numbytes = 0; - size_t got; - while(numbytes<4) { - lanlink.tcpsocket.Receive(inbuffer+numbytes, 4 - numbytes, got); - numbytes += got; - fdset.Clear(); - fdset.Add(lanlink.tcpsocket); - fdset.Wait(0.1); - cid->Ping(); - if(lanlink.terminate) { - lanlink.tcpsocket.Close(); - goto CloseInfoDisplay; - } - } - linkid = (int)READ16LE(&u16inbuffer[0]); - lanlink.numslaves = (int)READ16LE(&u16inbuffer[1]); - - cid->ShowConnect(linkid + 1, lanlink.numslaves - linkid); - - numbytes = 0; - inbuffer[0] = 1; - while(numbytesPing(); - if(lanlink.terminate) { - lanlink.tcpsocket.Close(); - goto CloseInfoDisplay; - } - } - - lanlink.connected = true; - - cid->Connected(); - -CloseInfoDisplay: - delete cid; - return; -} - void lclient::CheckConn(void){ size_t nr; lanlink.tcpsocket.Receive(inbuffer, 1, nr); diff --git a/src/gba/GBALink.h b/src/gba/GBALink.h index b72789ca..01446eac 100644 --- a/src/gba/GBALink.h +++ b/src/gba/GBALink.h @@ -1,8 +1,6 @@ #ifndef GBA_GBALINK_H #define GBA_GBALINK_H -#pragma once - /** * Link modes to be passed to InitLink */ @@ -15,13 +13,32 @@ enum LinkMode LINK_GAMECUBE_DOLPHIN }; +/** + * State of the connection attempt + */ +enum ConnectionState +{ + LINK_OK, + LINK_ERROR, + LINK_NEEDS_UPDATE, + LINK_ABORT +}; + /** * Initialize GBA linking * * @param mode Device to emulate, plugged to the GBA link port. * @return success */ -extern bool InitLink(LinkMode mode); +extern ConnectionState InitLink(LinkMode mode); + +/** + * Update a link connection request + * + * @param message Information message + * @param size Maximum message size + */ +extern ConnectionState ConnectLinkUpdate(char * const message, size_t size); /** * Get the currently enabled link mode @@ -30,6 +47,21 @@ extern bool InitLink(LinkMode mode); */ extern LinkMode GetLinkMode(); +/** + * Set the host to connect to when in socket mode + */ +extern void SetLinkServerHost(const char *host); + +/** + * Get the host relevant to context + * + * If in lan server mode, returns the external IP adress + * If in lan client mode, returns the IP adress of the host to connect to + * If in gamecube mode, returns the IP adress of the dolphin host + * + */ +extern void GetLinkServerHost(char * const host, size_t size); + /** * Set the current link mode to LINK_DISCONNECTED */ @@ -87,18 +119,8 @@ extern const char *MakeInstanceFilename(const char *Input); #ifndef NO_LINK // Link implementation -#include #include -class ServerInfoDisplay -{ -public: - virtual void ShowServerIP(const sf::IPAddress& addr) = 0; - virtual void ShowConnect(const int player) = 0; - virtual void Ping() = 0; - virtual void Connected() = 0; -}; - typedef struct { u16 linkdata[5]; u16 linkcmd; @@ -130,19 +152,10 @@ public: sf::SocketTCP tcpsocket[4]; sf::IPAddress udpaddr[4]; lserver(void); - bool Init(ServerInfoDisplay *); void Send(void); void Recv(void); }; -class ClientInfoDisplay { -public: - virtual void ConnectStart(const sf::IPAddress& addr) = 0; - virtual void Ping() = 0; - virtual void ShowConnect(const int player, const int togo) = 0; - virtual void Connected() = 0; -}; - class lclient{ sf::Selector fdset; char inbuffer[256], outbuffer[256]; @@ -157,7 +170,6 @@ public: sf::SocketTCP noblock; int numtransfers; lclient(void); - bool Init(sf::IPAddress, ClientInfoDisplay *); void Send(void); void Recv(void); void CheckConn(void); @@ -165,12 +177,10 @@ public: typedef struct { sf::SocketTCP tcpsocket; - //sf::SocketUDP udpsocket; int numslaves; - sf::Thread *thread; + int connectedSlaves; int type; bool server; - bool terminate; bool connected; bool speed; } LANLINKDATA; @@ -192,8 +202,6 @@ extern int linkid; #else // stubs to keep #ifdef's out of mainline -inline void JoyBusConnect() { } -inline void JoyBusShutdown() { } inline void JoyBusUpdate(int) { } inline bool InitLink() { return true; } diff --git a/src/win32/LinkOptions.cpp b/src/win32/LinkOptions.cpp index 52543f48..290b4667 100644 --- a/src/win32/LinkOptions.cpp +++ b/src/win32/LinkOptions.cpp @@ -689,7 +689,10 @@ void LinkOptions::GetAllData(LinkGeneral *src) if (newMode != oldMode) { CloseLink(); - InitLink(newMode); + ConnectionState state = InitLink(newMode); + if (state != LINK_OK) { + CloseLink(); + } } return; diff --git a/src/wx/guiinit.cpp b/src/wx/guiinit.cpp index d3b841cd..45a001d5 100644 --- a/src/wx/guiinit.cpp +++ b/src/wx/guiinit.cpp @@ -63,6 +63,7 @@ public: // attached to OK, so skip when OK void NetConnect(wxCommandEvent &ev) { + static const int length = 256; if(!dlg->Validate() || !dlg->TransferDataFromWindow()) return; update_opts(); // save fast flag and client host @@ -70,150 +71,62 @@ public: // Close any previous link CloseLink(); - wxString connmsg, pmsg; - - wxMutex lock; - wxCondition sig(lock); - lock.Lock(); - - bool done = false; + wxString connmsg; + wxString title; if(lanlink.server) { - lanlink.numslaves = n_players - 1; - class sid_t : public ServerInfoDisplay - { - wxMutex *lock; - wxCondition *sig; - wxString *connmsg, *pmsg; - bool *done; - bool conn[3]; - public: - sid_t(wxMutex *m, wxCondition *c, wxString *cm, wxString *pm, - bool *d) : - lock(m), sig(c), connmsg(cm), pmsg(pm), done(d) {} - void ShowServerIP(const sf::IPAddress &addr) { - wxString addr_s(addr.ToString().c_str(), wxConvLibc); - wxString msg; - msg.Printf(_("Server IP address is: %s\n"), addr_s.c_str()); - connmsg->append(msg); - conn[0] = conn[1] = conn[2] = false; - } - void ShowConnect(int player) { - wxString msg; - conn[player - 1] = true; - lock->Lock(); - pmsg->clear(); - for(int i = 0; i < 3; i++) - if(conn[i]) { - msg.Printf(_("Player %d connected\n"), i + 2); - pmsg->append(msg); - } - sig->Signal(); - lock->Unlock(); - } - void Ping() { - lock->Lock(); - sig->Signal(); - if(*done) - lanlink.terminate = true; - lock->Unlock(); - } - void Connected() { - lock->Lock(); - *done = true; - sig->Signal(); - lock->Unlock(); - } - }; - - sid_t* sid = new sid_t(&lock, &sig, &connmsg, &pmsg, &done); - - if (!ls.Init(sid)) { - wxLogError(_("Error occurred.\nPlease try again.")); - lock.Unlock(); - delete sid; - return; - } - - wxProgressDialog - pdlg(_("Waiting for clients..."), connmsg, - 100, dlg, wxPD_APP_MODAL|wxPD_CAN_ABORT|wxPD_ELAPSED_TIME); - - while(!done) { - if(!pdlg.Pulse(connmsg + pmsg)) - done = true; - sig.Wait(); - } + char host[length]; + GetLinkServerHost(host, length); + + lanlink.numslaves = n_players - 1; + + title.Printf(_("Waiting for clients...")); + connmsg.Printf(_("Server IP address is: %s\n"), wxString(host, wxConvLibc).c_str()); } else { - class cid_t : public ClientInfoDisplay - { - wxMutex *lock; - wxCondition *sig; - wxString *connmsg, *pmsg; - bool *done; - public: - cid_t(wxMutex *m, wxCondition *c, wxString *cm, wxString *pm, - bool *d) : - lock(m), sig(c), connmsg(cm), pmsg(pm), done(d) {} - void ConnectStart(const sf::IPAddress &addr) { - wxString addr_s(addr.ToString().c_str(), wxConvLibc); - connmsg->Printf(_("Connecting to %s\n"), addr_s.c_str()); - } - void ShowConnect(int player, int togo) { - wxString msg; - lock->Lock(); - pmsg->Printf(_("Connected as #%d\n"), player); - if(togo) - msg.Printf(_("Waiting for %d players to join"), togo); - else - msg = _("All players joined."); - pmsg->append(msg); - sig->Signal(); - lock->Unlock(); - } - void Ping() { - lock->Lock(); - sig->Signal(); - if(*done) - lanlink.terminate = true; - lock->Unlock(); - } - void Connected() { - lock->Lock(); - *done = true; - sig->Signal(); - lock->Unlock(); - } - }; - - cid_t* cid = new cid_t(&lock, &sig, &connmsg, &pmsg, &done); - - if (!lc.Init(sf::IPAddress(std::string(gopts.link_host.mb_str())), cid)) { - wxLogError(_("Error occurred.\nPlease try again.")); - lock.Unlock(); - delete cid; - return; - } - - wxProgressDialog - pdlg(_("Waiting for connection..."), connmsg, - 100, dlg, wxPD_APP_MODAL|wxPD_CAN_ABORT|wxPD_ELAPSED_TIME); - - while(!done) { - if(!pdlg.Pulse(connmsg + pmsg)) - done = true; - sig.Wait(); - } + SetLinkServerHost(gopts.link_host.mb_str()); + + title.Printf(_("Waiting for connection...")); + connmsg.Printf(_("Connecting to %s\n"), gopts.link_host.c_str()); } - lock.Unlock(); + + // Init link + ConnectionState state = InitLink(LINK_CABLE_SOCKET); + + // Display a progress dialog while the connection is establishing + if (state == LINK_NEEDS_UPDATE) { + wxProgressDialog pdlg(title, connmsg, + 100, dlg, wxPD_APP_MODAL | wxPD_CAN_ABORT | wxPD_ELAPSED_TIME); + + while (state == LINK_NEEDS_UPDATE) { + // Ask the core for updates + char message[length]; + state = ConnectLinkUpdate(message, length); + + connmsg = wxString(message, wxConvLibc); + + // Does the user want to abort? + if (!pdlg.Pulse(connmsg)) { + state = LINK_ABORT; + } + } + } + + // The user canceled the connection attempt + if (state == LINK_ABORT) { + CloseLink(); + } + + // Something failed during init + if (state == LINK_ERROR) { + CloseLink(); + wxLogError(_("Error occurred.\nPlease try again.")); + } + if(lanlink.connected) { - pmsg.Replace(wxT("\n"), wxT(" ")); - systemScreenMessage(pmsg); - - // Init link - InitLink(LINK_CABLE_SOCKET); - - ev.Skip(); // all OK + connmsg.Replace(wxT("\n"), wxT(" ")); + systemScreenMessage(connmsg); + + ev.Skip(); // all OK } } } net_link_handler; @@ -3228,7 +3141,10 @@ bool MainFrame::InitMore(void) } } - InitLink(linkMode); + ConnectionState linkState = InitLink(linkMode); + if (linkState != LINK_OK) { + CloseLink(); + } if (GetLinkMode() != LINK_DISCONNECTED) cmd_enable |= CMDEN_LINK_ANY;