tAll clients now use NetworkBuffer code for connect()ing, to allow support for … | |
git clone git://src.adamsgaard.dk/vaccinewars | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit d6e0ec90931c5375b3157cfbb9e4bb42c8cf13f6 | |
parent ec4529cf865fafa618e04da4a5cc3214e2667cd5 | |
Author: Ben Webb <[email protected]> | |
Date: Mon, 15 Oct 2001 16:04:18 +0000 | |
All clients now use NetworkBuffer code for connect()ing, to allow support for | |
SOCKS; "run from fights" Jet dialog made more usable; SOCKS5 user/password | |
authentication now supported by curses and GTK+ clients; "Sack Bitch" menu | |
item no longer hard-coded | |
Diffstat: | |
M src/AIPlayer.c | 104 +++++++++++++++++++++++++----… | |
M src/curses_client.c | 231 +++++++++++++++++++++++++----… | |
M src/gtk_client.c | 275 +++++++++++++++++++++++++----… | |
M src/message.c | 21 --------------------- | |
M src/message.h | 1 - | |
M src/network.c | 230 ++++++++++++++---------------… | |
M src/network.h | 12 ++++++++---- | |
M src/serverside.c | 3 ++- | |
8 files changed, 617 insertions(+), 260 deletions(-) | |
--- | |
diff --git a/src/AIPlayer.c b/src/AIPlayer.c | |
t@@ -60,6 +60,56 @@ static void AIHandleQuestion(char *Data,AICode AI,Player *A… | |
/* out where these locations are for itself. */ | |
int RealLoanShark,RealBank,RealGunShop,RealPub; | |
+static void AIConnectFailed(NetworkBuffer *netbuf) { | |
+ GString *errstr; | |
+ | |
+ errstr = g_string_new(_("Connection closed by remote host")); | |
+ if (netbuf->error) g_string_assign_error(errstr,netbuf->error); | |
+ g_log(NULL,G_LOG_LEVEL_CRITICAL, | |
+ _("Could not connect to dopewars server\n(%s)\n" | |
+ "AI Player terminating abnormally."),errstr->str); | |
+ g_string_free(errstr,TRUE); | |
+} | |
+ | |
+static void AIStartGame(Player *AIPlay) { | |
+ Client=Network=TRUE; | |
+ InitAbilities(AIPlay); | |
+ SendAbilities(AIPlay); | |
+ | |
+ AISetName(AIPlay); | |
+ g_message(_("Connection established\n")); | |
+} | |
+ | |
+static void DisplayConnectStatus(NetworkBuffer *netbuf,NBStatus oldstatus, | |
+ NBSocksStatus oldsocks) { | |
+ NBStatus status; | |
+ NBSocksStatus sockstat; | |
+ | |
+ status = netbuf->status; | |
+ sockstat = netbuf->sockstat; | |
+ if (oldstatus==status && oldsocks==sockstat) return; | |
+ | |
+ switch(status) { | |
+ case NBS_PRECONNECT: | |
+ break; | |
+ case NBS_SOCKSCONNECT: | |
+ switch(sockstat) { | |
+ case NBSS_METHODS: | |
+ g_print(_("Connected to SOCKS server %s...\n"),Socks.name); | |
+ break; | |
+ case NBSS_USERPASSWD: | |
+ g_print(_("Authenticating with SOCKS server\n")); | |
+ break; | |
+ case NBSS_CONNECT: | |
+ g_print(_("Asking SOCKS for connect to %s...\n"),ServerName); | |
+ break; | |
+ } | |
+ break; | |
+ case NBS_CONNECTED: | |
+ break; | |
+ } | |
+} | |
+ | |
void AIPlayerLoop() { | |
/* Main loop for AI players. Connects to server, plays game, */ | |
/* and then disconnects. */ | |
t@@ -67,45 +117,59 @@ void AIPlayerLoop() { | |
gchar *msg; | |
Player *AIPlay; | |
fd_set readfs,writefs; | |
- gboolean DoneOK,QuitRequest; | |
+ gboolean DoneOK,QuitRequest,datawaiting; | |
int MaxSock; | |
+ NBStatus oldstatus; | |
+ NBSocksStatus oldsocks; | |
+ NetworkBuffer *netbuf; | |
errstr=g_string_new(""); | |
AIPlay=g_new(Player,1); | |
FirstClient=AddPlayer(0,AIPlay,FirstClient); | |
g_message(_("AI Player started; attempting to contact server at %s:%d..."), | |
ServerName,Port); | |
- if (!SetupNetwork(errstr)) { | |
- g_log(NULL,G_LOG_LEVEL_CRITICAL, | |
- _("Could not connect to dopewars server\n(%s)\n" | |
- "AI Player terminating abnormally."),errstr->str); | |
- g_string_free(errstr,TRUE); | |
- return; | |
- } | |
- BindNetworkBufferToSocket(&AIPlay->NetBuf,ClientSock); | |
- | |
- InitAbilities(AIPlay); | |
- SendAbilities(AIPlay); | |
- | |
- AISetName(AIPlay); | |
- g_message(_("Connection established\n")); | |
/* Forget where the "special" locations are */ | |
RealLoanShark=RealBank=RealGunShop=RealPub=-1; | |
+ netbuf = &AIPlay->NetBuf; | |
+ oldstatus = netbuf->status; | |
+ oldsocks = netbuf->sockstat; | |
+ | |
+ if (!StartNetworkBufferConnect(netbuf,ServerName,Port)) { | |
+ AIConnectFailed(netbuf); return; | |
+ } else if (netbuf->status==NBS_CONNECTED) { | |
+ AIStartGame(AIPlay); | |
+ } else { | |
+ DisplayConnectStatus(netbuf,oldstatus,oldsocks); | |
+ } | |
+ | |
while (1) { | |
FD_ZERO(&readfs); | |
FD_ZERO(&writefs); | |
MaxSock=0; | |
- SetSelectForNetworkBuffer(&AIPlay->NetBuf,&readfs,&writefs,NULL,&MaxSock… | |
+ SetSelectForNetworkBuffer(netbuf,&readfs,&writefs,NULL,&MaxSock); | |
+ oldstatus = netbuf->status; | |
+ oldsocks = netbuf->sockstat; | |
if (bselect(MaxSock,&readfs,&writefs,NULL,NULL)==-1) { | |
if (errno==EINTR) continue; | |
printf("Error in select\n"); exit(1); | |
} | |
- if (RespondToSelect(&AIPlay->NetBuf,&readfs,&writefs,NULL,&DoneOK)) { | |
+ datawaiting=RespondToSelect(netbuf,&readfs,&writefs,NULL,&DoneOK); | |
+ | |
+ if (oldstatus!=NBS_CONNECTED && | |
+ (netbuf->status==NBS_CONNECTED || !DoneOK)) { | |
+ if (DoneOK) AIStartGame(AIPlay); | |
+ else { | |
+ AIConnectFailed(netbuf); break; | |
+ } | |
+ } else if (netbuf->status!=NBS_CONNECTED) { | |
+ DisplayConnectStatus(netbuf,oldstatus,oldsocks); | |
+ } | |
+ if (datawaiting && netbuf->status==NBS_CONNECTED) { | |
QuitRequest=FALSE; | |
while ((msg=GetWaitingPlayerMessage(AIPlay))!=NULL) { | |
if (HandleAIMessage(msg,AIPlay)) { | |
t@@ -113,7 +177,10 @@ void AIPlayerLoop() { | |
break; | |
} | |
} | |
- if (QuitRequest) break; | |
+ if (QuitRequest) { | |
+ g_print(_("AI Player terminated OK.\n")); | |
+ break; | |
+ } | |
} | |
if (!DoneOK) { | |
g_print(_("Connection to server lost!\n")); | |
t@@ -123,7 +190,6 @@ void AIPlayerLoop() { | |
ShutdownNetwork(AIPlay); | |
g_string_free(errstr,TRUE); | |
FirstClient=RemovePlayer(AIPlay,FirstClient); | |
- g_print(_("AI Player terminated OK.\n")); | |
} | |
void AISetName(Player *AIPlay) { | |
diff --git a/src/curses_client.c b/src/curses_client.c | |
t@@ -73,13 +73,16 @@ static void display_message(char *buf); | |
static void print_location(char *text); | |
static void print_status(Player *Play,gboolean DispDrug); | |
static char *nice_input(char *prompt,int sy,int sx,gboolean digitsonly, | |
- char *displaystr); | |
+ char *displaystr,char passwdchar); | |
static Player *ListPlayers(Player *Play,gboolean Select,char *Prompt); | |
static void HandleClientMessage(char *buf,Player *Play); | |
static void PrintMessage(const gchar *text); | |
static void GunShop(Player *Play); | |
static void LoanShark(Player *Play); | |
static void Bank(Player *Play); | |
+static void HttpAuthFunc(HttpConnection *conn,gboolean proxyauth, | |
+ gchar *realm,gpointer data); | |
+static void SocksAuthFunc(NetworkBuffer *netbuf,gpointer data); | |
static DispMode DisplayMode; | |
static gboolean QuitRequest; | |
t@@ -208,10 +211,10 @@ static void SelectServerManually(void) { | |
mvaddstr(17,1, | |
/* Prompts for hostname and port when selecting a server manually */ | |
_("Please enter the hostname and port of a dopewars server:-")); | |
- text=nice_input(_("Hostname: "),18,1,FALSE,ServerName); | |
+ text=nice_input(_("Hostname: "),18,1,FALSE,ServerName,'\0'); | |
AssignName(&ServerName,text); g_free(text); | |
PortText=g_strdup_printf("%d",Port); | |
- text=nice_input(_("Port: "),19,1,TRUE,PortText); | |
+ text=nice_input(_("Port: "),19,1,TRUE,PortText,'\0'); | |
Port=atoi(text); | |
g_free(text); g_free(PortText); | |
} | |
t@@ -228,7 +231,7 @@ static gboolean SelectServerFromMetaServer(Player *Play,GS… | |
gint index; | |
fd_set readfds,writefds; | |
int maxsock; | |
- gboolean DoneOK; | |
+ gboolean DoneOK,authOK; | |
HttpConnection *MetaConn; | |
attrset(TextAttr); | |
t@@ -236,7 +239,10 @@ static gboolean SelectServerFromMetaServer(Player *Play,G… | |
mvaddstr(17,1,_("Please wait... attempting to contact metaserver...")); | |
refresh(); | |
- if (!OpenMetaHttpConnection(&MetaConn)) { | |
+ if (OpenMetaHttpConnection(&MetaConn)) { | |
+ SetHttpAuthFunc(MetaConn,HttpAuthFunc,&authOK); | |
+ SetNetworkBufferUserPasswdFunc(&MetaConn->NetBuf,SocksAuthFunc,&authOK); | |
+ } else { | |
g_string_assign_error(errstr,MetaConn->NetBuf.error); | |
CloseHttpConnection(MetaConn); | |
return FALSE; | |
t@@ -260,10 +266,11 @@ static gboolean SelectServerFromMetaServer(Player *Play,… | |
if (c=='\f') wrefresh(curscr); | |
#endif | |
} | |
+ authOK=TRUE; /* Gets set to FALSE if authentication fails */ | |
if (RespondToSelect(&MetaConn->NetBuf,&readfds,&writefds,NULL,&DoneOK)) { | |
while (HandleWaitingMetaServerData(MetaConn,&ServerList,&DoneOK)) {} | |
} | |
- if (!DoneOK && HandleHttpCompletion(MetaConn)) { | |
+ if ((!DoneOK || !authOK) && HandleHttpCompletion(MetaConn)) { | |
if (IsHttpError(MetaConn)) { | |
g_string_assign_error(errstr,MetaConn->NetBuf.error); | |
CloseHttpConnection(MetaConn); | |
t@@ -331,11 +338,141 @@ static gboolean SelectServerFromMetaServer(Player *Play… | |
return TRUE; | |
} | |
+static void DisplayConnectStatus(NetworkBuffer *netbuf, | |
+ NBStatus oldstatus,NBSocksStatus oldsocks) { | |
+ NBStatus status; | |
+ NBSocksStatus sockstat; | |
+ GString *text; | |
+ | |
+ status = netbuf->status; | |
+ sockstat = netbuf->sockstat; | |
+ | |
+ if (oldstatus==status && oldsocks==sockstat) return; | |
+ | |
+ text=g_string_new(""); | |
+ | |
+ switch(status) { | |
+ case NBS_PRECONNECT: | |
+ break; | |
+ case NBS_SOCKSCONNECT: | |
+ switch(sockstat) { | |
+ case NBSS_METHODS: | |
+ g_string_sprintf(text,_("Connected to SOCKS server %s..."), | |
+ Socks.name); | |
+ break; | |
+ case NBSS_USERPASSWD: | |
+ g_string_assign(text,_("Authenticating with SOCKS server")); | |
+ break; | |
+ case NBSS_CONNECT: | |
+ g_string_sprintf(text,_("Asking SOCKS for connect to %s..."), | |
+ ServerName); | |
+ break; | |
+ } | |
+ break; | |
+ case NBS_CONNECTED: | |
+ break; | |
+ } | |
+ if (text->str[0]) { | |
+ mvaddstr(17,1,text->str); | |
+ refresh(); | |
+ } | |
+ g_string_free(text,TRUE); | |
+} | |
+ | |
+void HttpAuthFunc(HttpConnection *conn,gboolean proxyauth, | |
+ gchar *realm,gpointer data) { | |
+ gchar *text,*user,*password; | |
+ gboolean *authOK; | |
+ | |
+ authOK = (gboolean *)data; | |
+ | |
+ attrset(TextAttr); | |
+ clear_bottom(); | |
+ if (proxyauth) { | |
+ text = g_strdup_printf(_("Proxy authentication required for realm %s"), | |
+ realm); | |
+ } else { | |
+ text = g_strdup_printf(_("Authentication required for realm %s"),realm); | |
+ } | |
+ mvaddstr(17,1,text); | |
+ g_free(text); | |
+ | |
+ user=nice_input(_("User name: "),18,1,FALSE,NULL,'\0'); | |
+ password=nice_input(_("Password: "),19,1,FALSE,NULL,'*'); | |
+ | |
+ *authOK = SetHttpAuthentication(conn,proxyauth,user,password); | |
+ g_free(user); g_free(password); | |
+} | |
+ | |
+void SocksAuthFunc(NetworkBuffer *netbuf,gpointer data) { | |
+ gchar *user,*password; | |
+ gboolean *authOK; | |
+ | |
+ authOK = (gboolean *)data; | |
+ | |
+ attrset(TextAttr); | |
+ clear_bottom(); | |
+ mvaddstr(17,1,_("SOCKS authentication required")); | |
+ | |
+ user=nice_input(_("User name: "),18,1,FALSE,NULL,'\0'); | |
+ password=nice_input(_("Password: "),19,1,FALSE,NULL,'*'); | |
+ | |
+ *authOK = SendSocks5UserPasswd(netbuf,user,password); | |
+ g_free(user); g_free(password); | |
+} | |
+ | |
+static gboolean DoConnect(Player *Play,GString *errstr) { | |
+ NetworkBuffer *netbuf; | |
+ fd_set readfds,writefds; | |
+ int maxsock,c; | |
+ gboolean doneOK=TRUE,authOK=TRUE; | |
+ NBStatus oldstatus; | |
+ NBSocksStatus oldsocks; | |
+ | |
+ netbuf=&Play->NetBuf; | |
+ oldstatus = netbuf->status; | |
+ oldsocks = netbuf->sockstat; | |
+ | |
+ if (!StartNetworkBufferConnect(netbuf,ServerName,Port)) { | |
+ doneOK=FALSE; | |
+ } else { | |
+ SetNetworkBufferUserPasswdFunc(netbuf,SocksAuthFunc,&authOK); | |
+ if (netbuf->status!=NBS_CONNECTED) { | |
+ DisplayConnectStatus(netbuf,oldstatus,oldsocks); | |
+ do { | |
+ FD_ZERO(&readfds); FD_ZERO(&writefds); | |
+ FD_SET(0,&readfds); maxsock=1; | |
+ SetSelectForNetworkBuffer(netbuf,&readfds,&writefds,NULL,&maxsock); | |
+ if (bselect(maxsock,&readfds,&writefds,NULL,NULL)==-1) { | |
+ if (errno==EINTR) { CheckForResize(Play); continue; } | |
+ perror("bselect"); exit(1); | |
+ } | |
+ if (FD_ISSET(0,&readfds)) { | |
+ /* So that Ctrl-L works */ | |
+ c = getch(); | |
+#ifndef CYGWIN | |
+ if (c=='\f') wrefresh(curscr); | |
+#endif | |
+ } | |
+ oldstatus = netbuf->status; | |
+ oldsocks = netbuf->sockstat; | |
+ authOK=TRUE; | |
+ RespondToSelect(netbuf,&readfds,&writefds,NULL,&doneOK); | |
+ if (netbuf->status==NBS_CONNECTED) break; | |
+ DisplayConnectStatus(netbuf,oldstatus,oldsocks); | |
+ } while (doneOK && authOK); | |
+ } | |
+ } | |
+ | |
+ if (!doneOK || !authOK) g_string_assign_error(errstr,netbuf->error); | |
+ return (doneOK && authOK); | |
+} | |
+ | |
static gboolean ConnectToServer(Player *Play) { | |
/* Connects to a dopewars server. Prompts the user to select a server */ | |
/* if necessary. Returns TRUE, unless the user elected to quit the */ | |
/* program rather than choose a valid server. */ | |
- gboolean MetaOK=TRUE,NetOK=TRUE; | |
+ gboolean MetaOK=TRUE,NetOK=TRUE,firstrun=FALSE; | |
GString *errstr; | |
gchar *text; | |
int c; | |
t@@ -354,24 +491,27 @@ static gboolean ConnectToServer(Player *Play) { | |
ConnectMethod=CM_SINGLE; | |
g_string_free(errstr,TRUE); | |
return TRUE; | |
- } | |
+ } else firstrun=TRUE; | |
+ | |
while (1) { | |
attrset(TextAttr); | |
clear_bottom(); | |
- if (MetaOK) { | |
+ if (MetaOK && !firstrun) { | |
mvaddstr(17,1, | |
_("Please wait... attempting to contact dopewars server...")… | |
refresh(); | |
- NetOK=SetupNetwork(errstr); | |
+ NetOK=DoConnect(Play,errstr); | |
} | |
- if (!NetOK || !MetaOK) { | |
+ if (!NetOK || !MetaOK || firstrun) { | |
+ firstrun=FALSE; | |
+ clear_line(16); | |
clear_line(17); | |
if (!MetaOK) { | |
/* Display of an error while contacting the metaserver */ | |
mvaddstr(16,1,_("Cannot get metaserver details")); | |
text=g_strdup_printf(" (%s)",errstr->str); | |
mvaddstr(17,1,text); g_free(text); | |
- } else { | |
+ } else if (!NetOK) { | |
/* Display of an error message while trying to contact a dopewars server | |
(the error message itself is displayed on the next screen line) */ | |
mvaddstr(16,1,_("Could not start multiplayer dopewars")); | |
t@@ -381,16 +521,14 @@ static gboolean ConnectToServer(Player *Play) { | |
MetaOK=NetOK=TRUE; | |
attrset(PromptAttr); | |
mvaddstr(18,1, | |
- _("Will you... C>onnect to a different host and/or port")); | |
+ _("Will you... C>onnect to a named dopewars server")); | |
mvaddstr(19,1, | |
_(" L>ist the servers on the metaserver, and " | |
"select one")); | |
mvaddstr(20,1, | |
- _(" Q>uit (where you can start a server by " | |
- "typing ")); | |
- mvaddstr(21,1, | |
- _(" dopewars -s < /dev/null & )")); | |
- mvaddstr(22,1,_(" or P>lay single-player ? ")); | |
+ _(" Q>uit (where you can start a server " | |
+ "by typing \"dopewars -s\")")); | |
+ mvaddstr(21,1,_(" or P>lay single-player ? ")); | |
attrset(TextAttr); | |
/* Translate these 4 keys in line with the above options, keeping the order | |
t@@ -399,19 +537,17 @@ static gboolean ConnectToServer(Player *Play) { | |
switch(c) { | |
case 'Q': g_string_free(errstr,TRUE); | |
return FALSE; | |
- case 'P': ConnectMethod=CM_SINGLE; | |
- g_string_free(errstr,TRUE); | |
+ case 'P': g_string_free(errstr,TRUE); | |
return TRUE; | |
- case 'L': ConnectMethod=CM_META; | |
- MetaOK=SelectServerFromMetaServer(Play,errstr); | |
+ case 'L': MetaOK=SelectServerFromMetaServer(Play,errstr); | |
break; | |
- case 'C': ConnectMethod=CM_PROMPT; | |
- SelectServerManually(); | |
+ case 'C': SelectServerManually(); | |
break; | |
} | |
} else break; | |
} | |
g_string_free(errstr,TRUE); | |
+ Client=Network=TRUE; | |
return TRUE; | |
} | |
#endif /* NETWORKING */ | |
t@@ -493,7 +629,7 @@ static void DropDrugs(Player *Play) { | |
c--; | |
if (c<'A') { | |
addstr(Drug[i].Name); | |
- buf=nice_input(_("How many do you drop? "),23,8,TRUE,NULL); | |
+ buf=nice_input(_("How many do you drop? "),23,8,TRUE,NULL,'\0'); | |
c=atoi(buf); g_free(buf); | |
if (c>0) { | |
g_string_sprintf(text,"drug^%d^%d",i,-c); | |
t@@ -547,7 +683,7 @@ static void DealDrugs(Player *Play,gboolean Buy) { | |
CanAfford,CanCarry); | |
mvaddstr(23,2,text); | |
input=nice_input(_("How many do you buy? "),23,2+strlen(text), | |
- TRUE,NULL); | |
+ TRUE,NULL,'\0'); | |
c=atoi(input); g_free(input); g_free(text); | |
if (c>=0) { | |
text=g_strdup_printf("drug^%d^%d",DrugNum,c); | |
t@@ -559,7 +695,7 @@ static void DealDrugs(Player *Play,gboolean Buy) { | |
text=g_strdup_printf(_("You have %d. "),Play->Drugs[DrugNum].Carried); | |
mvaddstr(23,2,text); | |
input=nice_input(_("How many do you sell? "),23,2+strlen(text), | |
- TRUE,NULL); | |
+ TRUE,NULL,'\0'); | |
c=atoi(input); g_free(input); g_free(text); | |
if (c>=0) { | |
text=g_strdup_printf("drug^%d^%d",DrugNum,-c); | |
t@@ -655,7 +791,7 @@ static void change_name(Player *Play,gboolean nullname) { | |
gchar *NewName; | |
/* Prompt for player to change his/her name */ | |
- NewName=nice_input(_("New name: "),23,0,FALSE,NULL); | |
+ NewName=nice_input(_("New name: "),23,0,FALSE,NULL,'\0'); | |
if (NewName[0]) { | |
if (nullname) { | |
t@@ -990,7 +1126,8 @@ void LoanShark(Player *Play) { | |
attrset(PromptAttr); | |
/* Prompt for paying back loans from the loan shark */ | |
- text=nice_input(_("How much money do you pay back? "),19,1,TRUE,NULL); | |
+ text=nice_input(_("How much money do you pay back? "),19,1, | |
+ TRUE,NULL,'\0'); | |
attrset(TextAttr); | |
money=strtoprice(text); g_free(text); | |
if (money<0) money=0; | |
t@@ -1029,7 +1166,7 @@ void Bank(Player *Play) { | |
if (c=='L') return; | |
/* Prompt for putting money in or taking money out of the bank */ | |
- text=nice_input(_("How much money? "),19,1,TRUE,NULL); | |
+ text=nice_input(_("How much money? "),19,1,TRUE,NULL,'\0'); | |
money=strtoprice(text); g_free(text); | |
if (money<0) money=0; | |
t@@ -1482,7 +1619,7 @@ Player *ListPlayers(Player *Play,gboolean Select,char *P… | |
} | |
char *nice_input(char *prompt,int sy,int sx,gboolean digitsonly, | |
- char *displaystr) { | |
+ char *displaystr,char passwdchar) { | |
/* Displays the given "prompt" (if non-NULL) at coordinates sx,sy and */ | |
/* allows the user to input a string, which is returned. This is a */ | |
/* dynamically allocated string, and so must be freed by the calling */ | |
t@@ -1491,6 +1628,8 @@ char *nice_input(char *prompt,int sy,int sx,gboolean dig… | |
/* strtoprice routine understands this notation for a 1000000 or 1000 */ | |
/* multiplier) as well as a decimal point (. or ,) */ | |
/* If "displaystr" is non-NULL, it is taken as a default response. */ | |
+/* If "passwdchar" is non-zero, it is displayed instead of the user's */ | |
+/* keypresses (e.g. for entering passwords) */ | |
int i,c,x; | |
gboolean DecimalPoint,Suffix; | |
GString *text; | |
t@@ -1505,7 +1644,11 @@ char *nice_input(char *prompt,int sy,int sx,gboolean di… | |
} | |
attrset(TextAttr); | |
if (displaystr) { | |
- addstr(displaystr); | |
+ if (passwdchar) { | |
+ for (i=strlen(displaystr);i;i--) addch((guint)passwdchar); | |
+ } else { | |
+ addstr(displaystr); | |
+ } | |
i=strlen(displaystr); | |
text=g_string_new(displaystr); | |
} else { | |
t@@ -1530,16 +1673,16 @@ char *nice_input(char *prompt,int sy,int sx,gboolean d… | |
(!digitsonly && c>=32 && c!='^' && c<127)) { | |
g_string_append_c(text,c); | |
i++; | |
- addch((guint)c); | |
+ addch((guint)passwdchar ? passwdchar : c); | |
} else if (digitsonly && (c=='.' || c==',') && !DecimalPoint) { | |
g_string_append_c(text,'.'); | |
- addch((guint)c); | |
+ addch((guint)passwdchar ? passwdchar : c); | |
DecimalPoint=TRUE; | |
} else if (digitsonly && (c=='M' || c=='m' || c=='k' || c=='K') | |
&& !Suffix) { | |
g_string_append_c(text,c); | |
i++; | |
- addch((guint)c); | |
+ addch((guint)passwdchar ? passwdchar : c); | |
Suffix=TRUE; | |
} | |
} | |
t@@ -1574,6 +1717,7 @@ static void Curses_DoGame(Player *Play) { | |
char HaveWorthless; | |
Player *tmp; | |
struct sigaction sact; | |
+ gboolean justconnected=FALSE; | |
DisplayMode=DM_NONE; | |
QuitRequest=FALSE; | |
t@@ -1596,12 +1740,12 @@ static void Curses_DoGame(Player *Play) { | |
buf=NULL; | |
do { | |
g_free(buf); | |
- buf=nice_input(_("Hey dude, what's your name? "),17,1,FALSE,OldName); | |
+ buf=nice_input(_("Hey dude, what's your name? "),17,1,FALSE,OldName,'\0'… | |
} while (buf[0]==0); | |
#if NETWORKING | |
if (WantNetwork) { | |
if (!ConnectToServer(Play)) { end_curses(); exit(1); } | |
- BindNetworkBufferToSocket(&Play->NetBuf,ClientSock); | |
+ justconnected=TRUE; | |
} | |
#endif /* NETWORKING */ | |
print_status(Play,TRUE); | |
t@@ -1710,6 +1854,15 @@ static void Curses_DoGame(Player *Play) { | |
FD_ZERO(&writefs); | |
FD_SET(0,&readfs); MaxSock=1; | |
if (Client) { | |
+ if (justconnected) { | |
+/* Deal with any messages that came in while we were connect()ing */ | |
+ justconnected=FALSE; | |
+ while ((pt=GetWaitingPlayerMessage(Play))!=NULL) { | |
+ HandleClientMessage(pt,Play); | |
+ g_free(pt); | |
+ } | |
+ if (QuitRequest) return; | |
+ } | |
SetSelectForNetworkBuffer(&Play->NetBuf,&readfs,&writefs, | |
NULL,&MaxSock); | |
} | |
t@@ -1803,7 +1956,7 @@ static void Curses_DoGame(Player *Play) { | |
if (tmp) { | |
attrset(TextAttr); clear_line(22); | |
/* Prompt for sending player-player messages */ | |
- TalkMsg=nice_input(_("Talk: "),22,0,FALSE,NULL); | |
+ TalkMsg=nice_input(_("Talk: "),22,0,FALSE,NULL,'\0'); | |
if (TalkMsg[0]) { | |
SendClientMessage(Play,C_NONE,C_MSGTO,tmp,TalkMsg); | |
buf=g_strdup_printf("%s->%s: %s",GetPlayerName(Play), | |
t@@ -1815,7 +1968,7 @@ static void Curses_DoGame(Player *Play) { | |
} | |
} else if (c=='T' && Client) { | |
attrset(TextAttr); clear_line(22); | |
- TalkMsg=nice_input(_("Talk: "),22,0,FALSE,NULL); | |
+ TalkMsg=nice_input(_("Talk: "),22,0,FALSE,NULL,'\0'); | |
if (TalkMsg[0]) { | |
SendClientMessage(Play,C_NONE,C_MSG,NULL,TalkMsg); | |
buf=g_strdup_printf("%s: %s",GetPlayerName(Play),TalkMsg); | |
diff --git a/src/gtk_client.c b/src/gtk_client.c | |
t@@ -94,12 +94,17 @@ static void ListInventory(GtkWidget *widget,gpointer data); | |
static void NewGameDialog(void); | |
static void StartGame(void); | |
static void EndGame(void); | |
+static void Jet(GtkWidget *parent); | |
static void UpdateMenus(void); | |
+ | |
+#ifdef NETWORKING | |
+static void DisplayConnectStatus(struct StartGameStruct *widgets,gboolean meta, | |
+ NBStatus oldstatus,NBSocksStatus oldsocks); | |
static void AuthDialog(HttpConnection *conn, | |
gboolean proxyauth,gchar *realm, | |
gpointer data); | |
- | |
-#ifdef NETWORKING | |
+static void MetaSocksAuthDialog(NetworkBuffer *netbuf,gpointer data); | |
+static void SocksAuthDialog(NetworkBuffer *netbuf,gpointer data); | |
static void GetClientMessage(gpointer data,gint socket, | |
GdkInputCondition condition); | |
static void SocketStatus(NetworkBuffer *NetBuf,gboolean Read,gboolean Write); | |
t@@ -127,7 +132,6 @@ static void UpdateInventory(struct InventoryWidgets *Inven, | |
Inventory *Objects,int NumObjects, | |
gboolean AreDrugs); | |
static void JetButtonPressed(GtkWidget *widget,gpointer data); | |
-static void Jet(void); | |
static void DealDrugs(GtkWidget *widget,gpointer data); | |
static void DealGuns(GtkWidget *widget,gpointer data); | |
static void QuestionDialog(char *Data,Player *From); | |
t@@ -170,7 +174,9 @@ static GtkItemFactoryEntry menu_items[] = { | |
{ N_("/_Errands"),NULL,NULL,0,"<Branch>" }, | |
{ N_("/Errands/_Spy..."),NULL,SpyOnPlayer,0,NULL }, | |
{ N_("/Errands/_Tipoff..."),NULL,TipOff,0,NULL }, | |
- { N_("/Errands/Sack _Bitch..."),NULL,SackBitch,0,NULL }, | |
+/* N.B. "Sack Bitch" has to be recreated (and thus translated) at the start | |
+ of each game, below, so is not marked for gettext here */ | |
+ { "/Errands/S_ack Bitch...",NULL,SackBitch,0,NULL }, | |
{ N_("/Errands/_Get spy reports..."),NULL,GetSpyReports,0,NULL }, | |
{ N_("/_Help"),NULL,NULL,0,"<LastBranch>" }, | |
{ N_("/Help/_About..."),"F1",display_intro,0,NULL } | |
t@@ -282,33 +288,45 @@ void GetClientMessage(gpointer data,gint socket, | |
GdkInputCondition condition) { | |
gchar *pt; | |
NetworkBuffer *NetBuf; | |
- gboolean DoneOK,Connecting; | |
+ gboolean DoneOK,datawaiting; | |
+ NBStatus status,oldstatus; | |
+ NBSocksStatus oldsocks; | |
NetBuf = &ClientData.Play->NetBuf; | |
- Connecting = NetBuf->status != NBS_CONNECTED; | |
- if (PlayerHandleNetwork(ClientData.Play,condition&GDK_INPUT_READ, | |
- condition&GDK_INPUT_WRITE,&DoneOK) && !Connecting) { | |
- while ((pt=GetWaitingPlayerMessage(ClientData.Play))!=NULL) { | |
- HandleClientMessage(pt,ClientData.Play); | |
- g_free(pt); | |
- } | |
+ | |
+ oldstatus = NetBuf->status; | |
+ oldsocks = NetBuf->sockstat; | |
+ | |
+ datawaiting = PlayerHandleNetwork(ClientData.Play,condition&GDK_INPUT_READ, | |
+ condition&GDK_INPUT_WRITE,&DoneOK); | |
+ | |
+ status = NetBuf->status; | |
+ | |
+ if (status!=NBS_CONNECTED) { | |
+/* The start game dialog isn't visible once we're connected... */ | |
+ DisplayConnectStatus((struct StartGameStruct *)data,FALSE, | |
+ oldstatus,oldsocks); | |
} | |
- if (Connecting && (NetBuf->status==NBS_CONNECTED || !DoneOK)) { | |
- FinishServerConnect(data,DoneOK); | |
- if (DoneOK) { /* Just in case, clean up any messages that came in */ | |
- while ((pt=GetWaitingPlayerMessage(ClientData.Play))!=NULL) { | |
- HandleClientMessage(pt,ClientData.Play); | |
- g_free(pt); | |
- } | |
- } | |
- } else if (!DoneOK) { | |
- if (InGame) { | |
+ | |
+ if (oldstatus!=NBS_CONNECTED && (status==NBS_CONNECTED || !DoneOK)) { | |
+ FinishServerConnect(data,DoneOK); | |
+ } | |
+ if (status==NBS_CONNECTED && datawaiting) { | |
+ while ((pt=GetWaitingPlayerMessage(ClientData.Play))!=NULL) { | |
+ HandleClientMessage(pt,ClientData.Play); | |
+ g_free(pt); | |
+ } | |
+ } | |
+ if (!DoneOK) { | |
+ if (status==NBS_CONNECTED) { | |
/* The network connection to the server was dropped unexpectedly */ | |
- g_warning(_("Connection to server lost - switching to " | |
- "single player mode")); | |
- SwitchToSinglePlayer(ClientData.Play); | |
- UpdateMenus(); | |
- } | |
+ g_warning(_("Connection to server lost - switching to " | |
+ "single player mode")); | |
+ SwitchToSinglePlayer(ClientData.Play); | |
+ UpdateMenus(); | |
+ } else { | |
+ ShutdownNetworkBuffer(&ClientData.Play->NetBuf); | |
+ } | |
} | |
} | |
t@@ -355,7 +373,6 @@ void HandleClientMessage(char *pt,Player *Play) { | |
DisplayFightMessage(Data); break; | |
case C_PUSH: | |
/* The server admin has asked us to leave - so warn the user, and do so */ | |
- ShutdownNetworkBuffer(&Play->NetBuf); | |
g_warning(_("You have been pushed from the server.\n" | |
"Switching to single player mode.")); | |
SwitchToSinglePlayer(Play); | |
t@@ -363,7 +380,6 @@ void HandleClientMessage(char *pt,Player *Play) { | |
break; | |
case C_QUIT: | |
/* The server has sent us notice that it is shutting down */ | |
- ShutdownNetworkBuffer(&Play->NetBuf); | |
g_warning(_("The server has terminated.\n" | |
"Switching to single player mode.")); | |
SwitchToSinglePlayer(Play); | |
t@@ -416,6 +432,15 @@ void HandleClientMessage(char *pt,Player *Play) { | |
break; | |
case C_ENDLIST: | |
MenuItem=gtk_item_factory_get_widget(ClientData.Menu, | |
+ "<main>/Errands/Sack Bitch..."); | |
+ | |
+/* Text for the Errands/Sack Bitch menu item */ | |
+ text=dpg_strdup_printf(_("%/Sack Bitch menu item/S_ack %Tde"), | |
+ Names.Bitch); | |
+ SetAccelerator(MenuItem,text,NULL,NULL,NULL); | |
+ g_free(text); | |
+ | |
+ MenuItem=gtk_item_factory_get_widget(ClientData.Menu, | |
"<main>/Errands/Spy..."); | |
/* Text to update the Errands/Spy menu item with the price for spying */ | |
t@@ -656,8 +681,8 @@ static void FightCallback(GtkWidget *widget,gpointer data)… | |
if (CanRunHere) { | |
SendClientMessage(Play,C_NONE,C_FIGHTACT,NULL,"R"); | |
} else { | |
- gtk_widget_hide(FightDialog); | |
- Jet(); | |
+/* gtk_widget_hide(FightDialog);*/ | |
+ Jet(FightDialog); | |
} | |
break; | |
case 'F': case 'S': | |
t@@ -1135,11 +1160,11 @@ void JetButtonPressed(GtkWidget *widget,gpointer data)… | |
if (ClientData.Play->Flags & FIGHTING) { | |
DisplayFightMessage(NULL); | |
} else { | |
- Jet(); | |
+ Jet(NULL); | |
} | |
} | |
-void Jet(void) { | |
+void Jet(GtkWidget *parent) { | |
GtkWidget *dialog,*table,*button,*label,*vbox; | |
GtkAccelGroup *accel_group; | |
gint boxsize,i,row,col; | |
t@@ -1155,7 +1180,8 @@ void Jet(void) { | |
gtk_window_add_accel_group(GTK_WINDOW(dialog),accel_group); | |
gtk_window_set_modal(GTK_WINDOW(dialog),TRUE); | |
gtk_window_set_transient_for(GTK_WINDOW(dialog), | |
- GTK_WINDOW(ClientData.window)); | |
+ parent ? GTK_WINDOW(parent) | |
+ : GTK_WINDOW(ClientData.window)); | |
vbox=gtk_vbox_new(FALSE,7); | |
t@@ -1901,7 +1927,10 @@ _("Based on John E. Dell's old Drug Wars game, dopewars… | |
/* Label at the bottom of GTK+ 'about' dialog */ | |
_("\nFor information on the command line options, type dopewars -h at your\n" | |
"Unix prompt. This will display a help screen, listing the available " | |
-"options.")); | |
+"options.\n")); | |
+ gtk_box_pack_start(GTK_BOX(vbox),label,FALSE,FALSE,0); | |
+ | |
+ label=gtk_label_new("http://dopewars.sourceforge.net/"); | |
gtk_box_pack_start(GTK_BOX(vbox),label,FALSE,FALSE,0); | |
hsep=gtk_hseparator_new(); | |
t@@ -1934,12 +1963,12 @@ static gboolean GetStartGamePlayerName(struct StartGam… | |
} | |
} | |
-#ifdef NETWORKING | |
static void SetStartGameStatus(struct StartGameStruct *widgets,gchar *msg) { | |
gtk_label_set_text(GTK_LABEL(widgets->status), | |
msg ? msg : _("Status: Waiting for user input")); | |
} | |
+#ifdef NETWORKING | |
static void ConnectError(struct StartGameStruct *widgets,gboolean meta) { | |
GString *neterr; | |
gchar *text; | |
t@@ -1948,10 +1977,13 @@ static void ConnectError(struct StartGameStruct *widge… | |
if (meta) error=widgets->MetaConn->NetBuf.error; | |
else error=ClientData.Play->NetBuf.error; | |
- if (!error) return; | |
- | |
neterr = g_string_new(""); | |
- g_string_assign_error(neterr,error); | |
+ | |
+ if (error) { | |
+ g_string_assign_error(neterr,error); | |
+ } else { | |
+ g_string_assign(neterr,_("Connection closed by remote host")); | |
+ } | |
if (meta) { | |
/* Error: GTK+ client could not connect to the metaserver */ | |
t@@ -1978,19 +2010,28 @@ void FinishServerConnect(struct StartGameStruct *widge… | |
static void DoConnect(struct StartGameStruct *widgets) { | |
gchar *text; | |
+ NetworkBuffer *NetBuf; | |
+ NBStatus oldstatus; | |
+ NBSocksStatus oldsocks; | |
+ | |
+ NetBuf=&ClientData.Play->NetBuf; | |
+ | |
/* Message displayed during the attempted connect to a dopewars server */ | |
text=g_strdup_printf(_("Status: Attempting to contact %s..."),ServerName); | |
SetStartGameStatus(widgets,text); g_free(text); | |
/* Terminate any existing connection attempts */ | |
- ShutdownNetworkBuffer(&ClientData.Play->NetBuf); | |
+ ShutdownNetworkBuffer(NetBuf); | |
if (widgets->MetaConn) { | |
CloseHttpConnection(widgets->MetaConn); widgets->MetaConn=NULL; | |
} | |
- if (StartNetworkBufferConnect(&ClientData.Play->NetBuf,ServerName,Port)) { | |
- SetNetworkBufferCallBack(&ClientData.Play->NetBuf,SocketStatus, | |
- (gpointer)widgets); | |
+ oldstatus = NetBuf->status; | |
+ oldsocks = NetBuf->sockstat; | |
+ if (StartNetworkBufferConnect(NetBuf,ServerName,Port)) { | |
+ DisplayConnectStatus(widgets,FALSE,oldstatus,oldsocks); | |
+ SetNetworkBufferUserPasswdFunc(NetBuf,SocksAuthDialog,(gpointer)widgets); | |
+ SetNetworkBufferCallBack(NetBuf,SocketStatus,(gpointer)widgets); | |
} else { | |
ConnectError(widgets,FALSE); | |
} | |
t@@ -2051,15 +2092,19 @@ static void FillMetaServerList(struct StartGameStruct … | |
gtk_clist_thaw(GTK_CLIST(metaserv)); | |
} | |
-static void DisplayConnectStatus(struct StartGameStruct *widgets, | |
- gboolean meta, | |
- NBStatus oldstatus,NBSocksStatus oldsocks) { | |
+void DisplayConnectStatus(struct StartGameStruct *widgets,gboolean meta, | |
+ NBStatus oldstatus,NBSocksStatus oldsocks) { | |
NBStatus status; | |
NBSocksStatus sockstat; | |
gchar *text; | |
- status = widgets->MetaConn->NetBuf.status; | |
- sockstat = widgets->MetaConn->NetBuf.sockstat; | |
+ if (meta) { | |
+ status = widgets->MetaConn->NetBuf.status; | |
+ sockstat = widgets->MetaConn->NetBuf.sockstat; | |
+ } else { | |
+ status = ClientData.Play->NetBuf.status; | |
+ sockstat = ClientData.Play->NetBuf.sockstat; | |
+ } | |
if (oldstatus==status && sockstat==oldsocks) return; | |
switch (status) { | |
t@@ -2078,13 +2123,13 @@ static void DisplayConnectStatus(struct StartGameStruc… | |
break; | |
case NBSS_CONNECT: | |
text=g_strdup_printf(_("Status: Asking SOCKS for connect to %s..."), | |
- MetaServer.Name); | |
+ meta ? MetaServer.Name : ServerName); | |
SetStartGameStatus(widgets,text); g_free(text); | |
break; | |
} | |
break; | |
case NBS_CONNECTED: | |
- SetStartGameStatus(widgets, | |
+ if (meta) SetStartGameStatus(widgets, | |
_("Status: Obtaining server information from metaserver...")); | |
break; | |
} | |
t@@ -2162,6 +2207,8 @@ static void UpdateMetaServerList(GtkWidget *widget, | |
if (OpenMetaHttpConnection(&widgets->MetaConn)) { | |
metaserv=widgets->metaserv; | |
SetHttpAuthFunc(widgets->MetaConn,AuthDialog,(gpointer)widgets); | |
+ SetNetworkBufferUserPasswdFunc(&widgets->MetaConn->NetBuf, | |
+ MetaSocksAuthDialog,(gpointer)widgets); | |
SetNetworkBufferCallBack(&widgets->MetaConn->NetBuf, | |
MetaSocketStatus,(gpointer)widgets); | |
} else { | |
t@@ -2875,7 +2922,8 @@ void SackBitch(GtkWidget *widget,gpointer data) { | |
if (ClientData.Play->Bitches.Carried<=0) return; | |
/* Title of dialog to sack a bitch (%Tde = "Bitch" by default) */ | |
- title=dpg_strdup_printf(_("Sack %Tde"),Names.Bitch); | |
+ title=dpg_strdup_printf(_("%/Sack Bitch dialog title/Sack %Tde"), | |
+ Names.Bitch); | |
/* Confirmation message for sacking a bitch. (%tde = "guns", "drugs", | |
"bitch", respectively, by default) */ | |
t@@ -3168,6 +3216,7 @@ void DisplaySpyReports(Player *Play) { | |
gtk_widget_show_all(notebook); | |
} | |
+#ifdef NETWORKING | |
static void OKAuthDialog(GtkWidget *widget,GtkWidget *window) { | |
gtk_object_set_data(GTK_OBJECT(window),"authok",GINT_TO_POINTER(TRUE)); | |
gtk_widget_destroy(window); | |
t@@ -3239,7 +3288,7 @@ void AuthDialog(HttpConnection *conn,gboolean proxy,gcha… | |
vbox=gtk_vbox_new(FALSE,7); | |
- table=gtk_table_new(3,3,FALSE); | |
+ table=gtk_table_new(3,2,FALSE); | |
gtk_table_set_row_spacings(GTK_TABLE(table),10); | |
gtk_table_set_col_spacings(GTK_TABLE(table),5); | |
t@@ -3293,6 +3342,128 @@ void AuthDialog(HttpConnection *conn,gboolean proxy,gc… | |
gtk_widget_show_all(window); | |
} | |
+static void OKSocksAuth(GtkWidget *widget,GtkWidget *window) { | |
+ gtk_object_set_data(GTK_OBJECT(window),"authok",GINT_TO_POINTER(TRUE)); | |
+ gtk_widget_destroy(window); | |
+} | |
+ | |
+static void DestroySocksAuth(GtkWidget *window,gpointer data) { | |
+ GtkWidget *userentry,*passwdentry; | |
+ gchar *username=NULL,*password=NULL; | |
+ gpointer authok,meta; | |
+ NetworkBuffer *netbuf; | |
+ struct StartGameStruct *widgets; | |
+ NBStatus oldstatus; | |
+ NBSocksStatus oldsocks; | |
+ | |
+ authok = gtk_object_get_data(GTK_OBJECT(window),"authok"); | |
+ meta = gtk_object_get_data(GTK_OBJECT(window),"meta"); | |
+ userentry = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(window),"username"); | |
+ passwdentry = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(window), | |
+ "password"); | |
+ netbuf = (NetworkBuffer *)gtk_object_get_data(GTK_OBJECT(window),"netbuf"); | |
+ widgets = (struct StartGameStruct *)gtk_object_get_data(GTK_OBJECT(window), | |
+ "widgets"); | |
+ | |
+ g_assert(userentry && passwdentry && netbuf); | |
+ | |
+ if (authok) { | |
+ username = gtk_editable_get_chars(GTK_EDITABLE(userentry),0,-1); | |
+ password = gtk_editable_get_chars(GTK_EDITABLE(passwdentry),0,-1); | |
+ } | |
+ | |
+ oldstatus = netbuf->status; | |
+ oldsocks = netbuf->sockstat; | |
+ if (!SendSocks5UserPasswd(netbuf,username,password)) { | |
+ if (meta) MetaDone(widgets); else ConnectError(widgets,FALSE); | |
+ } else { | |
+ DisplayConnectStatus(widgets,GPOINTER_TO_INT(meta),oldstatus,oldsocks); | |
+ } | |
+ g_free(username); g_free(password); | |
+} | |
+ | |
+static void RealSocksAuthDialog(NetworkBuffer *netbuf,gboolean meta, | |
+ gpointer data) { | |
+ GtkWidget *window,*button,*hsep,*vbox,*label,*entry,*table,*hbbox; | |
+ struct StartGameStruct *widgets; | |
+ | |
+ widgets = (struct StartGameStruct *)data; | |
+ | |
+ window=gtk_window_new(GTK_WINDOW_DIALOG); | |
+ gtk_signal_connect(GTK_OBJECT(window),"destroy", | |
+ GTK_SIGNAL_FUNC(DestroySocksAuth),NULL); | |
+ gtk_object_set_data(GTK_OBJECT(window),"netbuf",(gpointer)netbuf); | |
+ gtk_object_set_data(GTK_OBJECT(window),"meta",GINT_TO_POINTER(meta)); | |
+ gtk_object_set_data(GTK_OBJECT(window),"widgets",(gpointer)widgets); | |
+ | |
+/* Title of dialog for authenticating with a SOCKS server */ | |
+ gtk_window_set_title(GTK_WINDOW(window),_("SOCKS Authentication Required")); | |
+ | |
+ gtk_window_set_modal(GTK_WINDOW(window),TRUE); | |
+ gtk_window_set_transient_for(GTK_WINDOW(window), | |
+ GTK_WINDOW(ClientData.window)); | |
+ gtk_container_set_border_width(GTK_CONTAINER(window),7); | |
+ | |
+ vbox=gtk_vbox_new(FALSE,7); | |
+ | |
+ table=gtk_table_new(2,2,FALSE); | |
+ gtk_table_set_row_spacings(GTK_TABLE(table),10); | |
+ gtk_table_set_col_spacings(GTK_TABLE(table),5); | |
+ | |
+ label=gtk_label_new("User name:"); | |
+ gtk_table_attach_defaults(GTK_TABLE(table),label,0,1,0,1); | |
+ | |
+ entry=gtk_entry_new(); | |
+ gtk_object_set_data(GTK_OBJECT(window),"username",(gpointer)entry); | |
+ gtk_table_attach_defaults(GTK_TABLE(table),entry,1,2,0,1); | |
+ | |
+ label=gtk_label_new("Password:"); | |
+ gtk_table_attach_defaults(GTK_TABLE(table),label,0,1,1,2); | |
+ | |
+ entry=gtk_entry_new(); | |
+ gtk_object_set_data(GTK_OBJECT(window),"password",(gpointer)entry); | |
+ | |
+#ifdef HAVE_FIXED_GTK | |
+ /* GTK+ versions earlier than 1.2.10 do bad things with this */ | |
+ gtk_entry_set_visibility(GTK_ENTRY(entry),FALSE); | |
+#endif | |
+ | |
+ gtk_table_attach_defaults(GTK_TABLE(table),entry,1,2,1,2); | |
+ | |
+ gtk_box_pack_start(GTK_BOX(vbox),table,TRUE,TRUE,0); | |
+ | |
+ hsep=gtk_hseparator_new(); | |
+ gtk_box_pack_start(GTK_BOX(vbox),hsep,FALSE,FALSE,0); | |
+ | |
+ hbbox = gtk_hbutton_box_new(); | |
+ | |
+ button=gtk_button_new_with_label(_("OK")); | |
+ gtk_signal_connect(GTK_OBJECT(button),"clicked", | |
+ GTK_SIGNAL_FUNC(OKSocksAuth),(gpointer)window); | |
+ gtk_box_pack_start(GTK_BOX(hbbox),button,TRUE,TRUE,0); | |
+ | |
+ button=gtk_button_new_with_label(_("Cancel")); | |
+ gtk_signal_connect_object(GTK_OBJECT(button),"clicked", | |
+ GTK_SIGNAL_FUNC(gtk_widget_destroy), | |
+ (gpointer)window); | |
+ gtk_box_pack_start(GTK_BOX(hbbox),button,TRUE,TRUE,0); | |
+ | |
+ gtk_box_pack_start(GTK_BOX(vbox),hbbox,TRUE,TRUE,0); | |
+ | |
+ gtk_container_add(GTK_CONTAINER(window),vbox); | |
+ gtk_widget_show_all(window); | |
+} | |
+ | |
+void MetaSocksAuthDialog(NetworkBuffer *netbuf,gpointer data) { | |
+ RealSocksAuthDialog(netbuf,TRUE,data); | |
+} | |
+ | |
+void SocksAuthDialog(NetworkBuffer *netbuf,gpointer data) { | |
+ RealSocksAuthDialog(netbuf,FALSE,data); | |
+} | |
+ | |
+#endif /* NETWORKING */ | |
+ | |
#else | |
#include <glib.h> | |
diff --git a/src/message.c b/src/message.c | |
t@@ -714,27 +714,6 @@ price_t GetNextPrice(gchar **Data,price_t Default) { | |
if (Word) return strtoprice(Word); else return Default; | |
} | |
-#if NETWORKING | |
-gboolean SetupNetwork(GString *errstr) { | |
-/* Sets up the connection from the client to the server. If the connection */ | |
-/* is successful, Network and Client are set to TRUE, and ClientSock is a */ | |
-/* file descriptor for the newly-opened socket. TRUE is returned. If the */ | |
-/* connection fails, FALSE is returned, and errstr (if non-NULL) is filled */ | |
-/* with a descriptive error message. */ | |
- LastError *err; | |
- | |
- Network=Client=Server=FALSE; | |
- if (StartConnect(&ClientSock,ServerName,Port,FALSE,&err)) { | |
- Client=Network=TRUE; | |
- return TRUE; | |
- } else { | |
- if (errstr) g_string_assign_error(errstr,err); | |
- FreeError(err); | |
- return FALSE; | |
- } | |
-} | |
-#endif /* NETWORKING */ | |
- | |
void SwitchToSinglePlayer(Player *Play) { | |
/* Called when the client is pushed off the server, or the server */ | |
/* terminates. Using the client information, starts a local server */ | |
diff --git a/src/message.h b/src/message.h | |
t@@ -109,7 +109,6 @@ gchar *GetNextWord(gchar **Data,gchar *Default); | |
void AssignNextWord(gchar **Data,gchar **Dest); | |
int GetNextInt(gchar **Data,int Default); | |
price_t GetNextPrice(gchar **Data,price_t Default); | |
-gboolean SetupNetwork(GString *errstr); | |
void ShutdownNetwork(Player *Play); | |
void SwitchToSinglePlayer(Player *Play); | |
int ProcessMessage(char *Msg,Player *Play,Player **Other,AICode *AI, | |
diff --git a/src/network.c b/src/network.c | |
t@@ -66,9 +66,8 @@ typedef enum { | |
static gboolean StartSocksNegotiation(NetworkBuffer *NetBuf,gchar *RemoteHost, | |
unsigned RemotePort); | |
-static gchar *GetWaitingData(NetworkBuffer *NetBuf,int numbytes); | |
-static gchar *PeekWaitingData(NetworkBuffer *NetBuf,int numbytes); | |
-static gchar *ExpandWriteBuffer(ConnBuf *conn,int numbytes); | |
+static gboolean StartConnect(int *fd,gchar *RemoteHost,unsigned RemotePort, | |
+ gboolean *doneOK,LastError **error); | |
#ifdef CYGWIN | |
t@@ -186,16 +185,18 @@ void SetNetworkBufferCallBack(NetworkBuffer *NetBuf,NBCa… | |
} | |
void SetNetworkBufferUserPasswdFunc(NetworkBuffer *NetBuf, | |
- NBUserPasswd userpasswd) { | |
+ NBUserPasswd userpasswd,gpointer data) { | |
/* Sets the function used to obtain a username and password for SOCKS5 */ | |
/* username/password authentication */ | |
NetBuf->userpasswd=userpasswd; | |
+ NetBuf->userpasswddata=data; | |
} | |
void BindNetworkBufferToSocket(NetworkBuffer *NetBuf,int fd) { | |
/* Sets up the given network buffer to handle data being sent/received */ | |
/* through the given socket */ | |
NetBuf->fd=fd; | |
+ SetBlocking(fd,FALSE); /* We only deal with non-blocking sockets */ | |
NetBuf->status=NBS_CONNECTED; /* Assume the socket is connected */ | |
} | |
t@@ -209,6 +210,7 @@ gboolean StartNetworkBufferConnect(NetworkBuffer *NetBuf,g… | |
unsigned RemotePort) { | |
gchar *realhost; | |
unsigned realport; | |
+ gboolean doneOK; | |
ShutdownNetworkBuffer(NetBuf); | |
t@@ -220,20 +222,22 @@ gboolean StartNetworkBufferConnect(NetworkBuffer *NetBuf… | |
realport = RemotePort; | |
} | |
- if (StartConnect(&NetBuf->fd,realhost,realport,TRUE,&NetBuf->error)) { | |
- NetBuf->WaitConnect=TRUE; | |
+ if (StartConnect(&NetBuf->fd,realhost,realport,&doneOK,&NetBuf->error)) { | |
+/* If we connected immediately, then set status, otherwise signal that we're | |
+ waiting for the connect to complete */ | |
+ if (doneOK) { | |
+ NetBuf->status = NetBuf->socks ? NBS_SOCKSCONNECT : NBS_CONNECTED; | |
+ NetBuf->sockstat = NBSS_METHODS; | |
+ } else { | |
+ NetBuf->WaitConnect=TRUE; | |
+ } | |
- if (NetBuf->socks) { | |
- if (!StartSocksNegotiation(NetBuf,RemoteHost,RemotePort)) { | |
- NetBuf->WaitConnect=FALSE; | |
- return FALSE; | |
- } else { | |
- NetBuf->status = NBS_SOCKSCONNECT; | |
- NetBuf->sockstat = NBSS_METHODS; | |
- } | |
+ if (NetBuf->socks && !StartSocksNegotiation(NetBuf,RemoteHost,RemotePort))… | |
+ return FALSE; | |
} | |
-/* Notify the owner if necessary to check for the connection completing */ | |
+/* Notify the owner if necessary to check for the connection completing | |
+ and/or for data to be writeable */ | |
NetBufCallBack(NetBuf); | |
return TRUE; | |
t@@ -392,7 +396,7 @@ static gboolean Socks5UserPasswd(NetworkBuffer *NetBuf) { | |
/* Request a username and password (the callback function should in turn | |
call SendSocks5UserPasswd when it's done) */ | |
NetBuf->sockstat = NBSS_USERPASSWD; | |
- (*NetBuf->userpasswd)(NetBuf); | |
+ (*NetBuf->userpasswd)(NetBuf,NetBuf->userpasswddata); | |
return TRUE; | |
} | |
} | |
t@@ -403,13 +407,13 @@ gboolean SendSocks5UserPasswd(NetworkBuffer *NetBuf,gcha… | |
guint addlen; | |
ConnBuf *conn; | |
- if (!user || !password) { | |
+ if (!user || !password || !user[0] || !password[0]) { | |
SetError(&NetBuf->error,&ETSocks,SEC_USERCANCEL,NULL); | |
return FALSE; | |
} | |
conn=&NetBuf->negbuf; | |
addlen = 3 + strlen(user) + strlen(password); | |
- addpt = ExpandWriteBuffer(conn,addlen); | |
+ addpt = ExpandWriteBuffer(conn,addlen,&NetBuf->error); | |
if (!addpt || strlen(user)>255 || strlen(password)>255) { | |
SetError(&NetBuf->error,ET_CUSTOM,E_FULLBUF,NULL); | |
return FALSE; | |
t@@ -419,13 +423,8 @@ gboolean SendSocks5UserPasswd(NetworkBuffer *NetBuf,gchar… | |
strcpy(&addpt[2],user); | |
addpt[2+strlen(user)] = strlen(password); | |
strcpy(&addpt[3+strlen(user)],password); | |
- g_free(user); g_free(password); | |
- conn->DataPresent+=addlen; | |
- | |
-/* If the buffer was empty before, we may need to tell the owner to check | |
- the socket for write-ready status */ | |
- if ((gchar *)addpt==conn->Data) NetBufCallBack(NetBuf); | |
+ CommitWriteBuffer(NetBuf,conn,addpt,addlen); | |
return TRUE; | |
} | |
t@@ -445,11 +444,8 @@ static gboolean Socks5Connect(NetworkBuffer *NetBuf) { | |
g_assert(sizeof(netport)==2); | |
addlen = hostlen + 7; | |
- addpt = ExpandWriteBuffer(conn,addlen); | |
- if (!addpt) { | |
- SetError(&NetBuf->error,ET_CUSTOM,E_FULLBUF,NULL); | |
- return FALSE; | |
- } | |
+ addpt = ExpandWriteBuffer(conn,addlen,&NetBuf->error); | |
+ if (!addpt) return FALSE; | |
addpt[0] = 5; /* SOCKS version 5 */ | |
addpt[1] = 1; /* CONNECT */ | |
addpt[2] = 0; /* reserved - must be zero */ | |
t@@ -459,13 +455,9 @@ static gboolean Socks5Connect(NetworkBuffer *NetBuf) { | |
memcpy(&addpt[5+hostlen],&netport,sizeof(netport)); | |
NetBuf->sockstat = NBSS_CONNECT; | |
- g_print("FIXME: SOCKS5 CONNECT request sent\n"); | |
- | |
- conn->DataPresent+=addlen; | |
+/* g_print("FIXME: SOCKS5 CONNECT request sent\n");*/ | |
-/* If the buffer was empty before, we may need to tell the owner to check | |
- the socket for write-ready status */ | |
- if ((gchar *)addpt==conn->Data) NetBufCallBack(NetBuf); | |
+ CommitWriteBuffer(NetBuf,conn,addpt,addlen); | |
return TRUE; | |
} | |
t@@ -476,23 +468,18 @@ static gboolean HandleSocksReply(NetworkBuffer *NetBuf) { | |
guint replylen; | |
gboolean retval=TRUE; | |
if (NetBuf->socks->version==5) { | |
-g_print("Handling SOCKS5 reply\n"); | |
if (NetBuf->sockstat == NBSS_METHODS) { | |
data = GetWaitingData(NetBuf,2); | |
if (data) { | |
retval=FALSE; | |
- g_print("FIXME: Reply from SOCKS5 server: %d %d\n",data[0],data[1]… | |
if (data[0]!=5) { | |
SetError(&NetBuf->error,&ETSocks,SEC_VERSION,NULL); | |
- } else if (data[1]!=0 && data[1]!=2) { | |
- SetError(&NetBuf->error,&ETSocks,SEC_NOMETHODS,NULL); | |
+ } else if (data[1]==SM_NOAUTH) { | |
+ retval=Socks5Connect(NetBuf); | |
+ } else if (data[1]==SM_USERPASSWD) { | |
+ retval=Socks5UserPasswd(NetBuf); | |
} else { | |
- g_print("FIXME: Using SOCKS5 method %d\n",data[1]); | |
- if (data[1]==SM_NOAUTH) { | |
- retval=Socks5Connect(NetBuf); | |
- } else if (data[1]==SM_USERPASSWD) { | |
- retval=Socks5UserPasswd(NetBuf); | |
- } | |
+ SetError(&NetBuf->error,&ETSocks,SEC_NOMETHODS,NULL); | |
} | |
g_free(data); | |
} | |
t@@ -500,9 +487,7 @@ g_print("Handling SOCKS5 reply\n"); | |
data = GetWaitingData(NetBuf,2); | |
if (data) { | |
retval=FALSE; | |
- if (data[0]!=5) { | |
- SetError(&NetBuf->error,&ETSocks,SEC_VERSION,NULL); | |
- } else if (data[1]!=0) { | |
+ if (data[1]!=0) { | |
SetError(&NetBuf->error,&ETSocks,SEC_AUTHFAILED,NULL); | |
} else { | |
retval=Socks5Connect(NetBuf); | |
t@@ -510,7 +495,6 @@ g_print("Handling SOCKS5 reply\n"); | |
g_free(data); | |
} | |
} else if (NetBuf->sockstat == NBSS_CONNECT) { | |
-g_print("FIXME: SOCKS5 connect reply\n"); | |
data = PeekWaitingData(NetBuf,5); | |
if (data) { | |
retval=FALSE; | |
t@@ -531,10 +515,9 @@ g_print("FIXME: SOCKS5 connect reply\n"); | |
else replylen+=data[4]; /* FQDN */ | |
data = GetWaitingData(NetBuf,replylen); | |
if (data) { | |
- g_print("FIXME: SOCKS5 successful connect\n"); | |
- if (addrtype==1) g_print("IPv4 address %d.%d.%d.%d\n",data[4],d… | |
+/* if (addrtype==1) g_print("IPv4 address %d.%d.%d.%d\n",data[4]… | |
else if (addrtype==4) g_print("IPv6 address\n"); | |
- else g_print("FQDN\n"); | |
+ else g_print("FQDN\n");*/ | |
NetBuf->status = NBS_CONNECTED; | |
g_free(data); | |
NetBufCallBack(NetBuf); /* status has changed */ | |
t@@ -584,13 +567,17 @@ static gboolean DoNetworkBufferStuff(NetworkBuffer *NetB… | |
retval=FinishConnect(NetBuf->fd,&NetBuf->error); | |
ConnectDone=TRUE; | |
NetBuf->WaitConnect=FALSE; | |
- if (!NetBuf->socks) { | |
-g_print("FIXME: Non-SOCKS successful connect\n"); | |
- NetBuf->status = NBS_CONNECTED; | |
- } | |
- if (!retval) { | |
- *WriteOK=FALSE; | |
+ if (retval) { | |
+ if (NetBuf->socks) { | |
+ NetBuf->status = NBS_SOCKSCONNECT; | |
+ NetBuf->sockstat = NBSS_METHODS; | |
+ } else { | |
+ NetBuf->status = NBS_CONNECTED; | |
+ } | |
+ } else { | |
+ NetBuf->status = NBS_PRECONNECT; | |
+ *WriteOK=FALSE; | |
} | |
} | |
} else { | |
t@@ -777,18 +764,30 @@ gboolean ReadDataFromWire(NetworkBuffer *NetBuf) { | |
return TRUE; | |
} | |
-gchar *ExpandWriteBuffer(ConnBuf *conn,int numbytes) { | |
- int newlen; | |
- newlen = conn->DataPresent + numbytes; | |
- if (newlen > conn->Length) { | |
- conn->Length*=2; | |
- conn->Length=MAX(conn->Length,newlen); | |
- if (conn->Length > MAXWRITEBUF) conn->Length=MAXWRITEBUF; | |
- if (newlen > conn->Length) return NULL; | |
- conn->Data=g_realloc(conn->Data,conn->Length); | |
- } | |
+gchar *ExpandWriteBuffer(ConnBuf *conn,int numbytes,LastError **error) { | |
+ int newlen; | |
+ newlen = conn->DataPresent + numbytes; | |
+ if (newlen > conn->Length) { | |
+ conn->Length*=2; | |
+ conn->Length=MAX(conn->Length,newlen); | |
+ if (conn->Length > MAXWRITEBUF) conn->Length=MAXWRITEBUF; | |
+ if (newlen > conn->Length) { | |
+ if (error) SetError(error,ET_CUSTOM,E_FULLBUF,NULL); | |
+ return NULL; | |
+ } | |
+ conn->Data=g_realloc(conn->Data,conn->Length); | |
+ } | |
- return (&conn->Data[conn->DataPresent]); | |
+ return (&conn->Data[conn->DataPresent]); | |
+} | |
+ | |
+void CommitWriteBuffer(NetworkBuffer *NetBuf,ConnBuf *conn, | |
+ gchar *addpt,guint addlen) { | |
+ conn->DataPresent+=addlen; | |
+ | |
+/* If the buffer was empty before, we may need to tell the owner to check | |
+ the socket for write-ready status */ | |
+ if (NetBuf && addpt==conn->Data) NetBufCallBack(NetBuf); | |
} | |
void QueueMessageForSend(NetworkBuffer *NetBuf,gchar *data) { | |
t@@ -804,16 +803,13 @@ void QueueMessageForSend(NetworkBuffer *NetBuf,gchar *da… | |
if (!data) return; | |
addlen = strlen(data)+1; | |
- addpt = ExpandWriteBuffer(conn,addlen); | |
+ addpt = ExpandWriteBuffer(conn,addlen,NULL); | |
if (!addpt) return; | |
memcpy(addpt,data,addlen); | |
- conn->DataPresent+=addlen; | |
addpt[addlen-1]=NetBuf->Terminator; | |
-/* If the buffer was empty before, we may need to tell the owner to check | |
- the socket for write-ready status */ | |
- if (addpt==conn->Data) NetBufCallBack(NetBuf); | |
+ CommitWriteBuffer(NetBuf,conn,addpt,addlen); | |
} | |
static struct hostent *LookupHostname(gchar *host,LastError **error) { | |
t@@ -837,8 +833,8 @@ gboolean StartSocksNegotiation(NetworkBuffer *NetBuf,gchar… | |
guint addlen,i; | |
struct in_addr *haddr; | |
unsigned short int netport; | |
-#ifdef CYGWIN | |
gchar *username=NULL; | |
+#ifdef CYGWIN | |
DWORD bufsize; | |
#else | |
struct passwd *pwd; | |
t@@ -850,28 +846,19 @@ gboolean StartSocksNegotiation(NetworkBuffer *NetBuf,gch… | |
num_methods=1; | |
if (NetBuf->userpasswd) num_methods++; | |
addlen=2+num_methods; | |
- addpt = ExpandWriteBuffer(conn,addlen); | |
- if (!addpt) { | |
- SetError(&NetBuf->error,ET_CUSTOM,E_FULLBUF,NULL); | |
- return FALSE; | |
- } | |
+ addpt = ExpandWriteBuffer(conn,addlen,&NetBuf->error); | |
+ if (!addpt) return FALSE; | |
addpt[0] = 5; /* SOCKS version 5 */ | |
addpt[1] = num_methods; | |
i=2; | |
addpt[i++] = SM_NOAUTH; | |
if (NetBuf->userpasswd) addpt[i++] = SM_USERPASSWD; | |
- g_print("FIXME: SOCKS5 methods request sent\n"); | |
- | |
- conn->DataPresent+=addlen; | |
- | |
g_free(NetBuf->host); | |
NetBuf->host = g_strdup(RemoteHost); | |
NetBuf->port = RemotePort; | |
-/* If the buffer was empty before, we may need to tell the owner to check | |
- the socket for write-ready status */ | |
- if ((gchar *)addpt==conn->Data) NetBufCallBack(NetBuf); | |
+ CommitWriteBuffer(NetBuf,conn,addpt,addlen); | |
return TRUE; | |
} | |
t@@ -879,27 +866,33 @@ gboolean StartSocksNegotiation(NetworkBuffer *NetBuf,gch… | |
he = LookupHostname(RemoteHost,&NetBuf->error); | |
if (!he) return FALSE; | |
-#ifdef CYGWIN | |
- bufsize=0; | |
- WNetGetUser(NULL,username,&bufsize); | |
- if (GetLastError()!=ERROR_MORE_DATA) { | |
- SetError(&NetBuf->error,ET_WIN32,GetLastError(),NULL); | |
- return FALSE; | |
+ if (NetBuf->socks->user && NetBuf->socks->user[0]) { | |
+ username = g_strdup(NetBuf->socks->user); | |
} else { | |
- username=g_malloc(bufsize); | |
- if (WNetGetUser(NULL,username,&bufsize)!=NO_ERROR) { | |
+#ifdef CYGWIN | |
+ bufsize=0; | |
+ WNetGetUser(NULL,username,&bufsize); | |
+ if (GetLastError()!=ERROR_MORE_DATA) { | |
SetError(&NetBuf->error,ET_WIN32,GetLastError(),NULL); | |
return FALSE; | |
+ } else { | |
+ username=g_malloc(bufsize); | |
+ if (WNetGetUser(NULL,username,&bufsize)!=NO_ERROR) { | |
+ SetError(&NetBuf->error,ET_WIN32,GetLastError(),NULL); | |
+ return FALSE; | |
+ } | |
} | |
- } | |
-g_print("username %s\n",username); | |
- addlen=9+strlen(username); | |
#else | |
- pwd = getpwuid(getuid()); | |
- if (!pwd || !pwd->pw_name) return FALSE; | |
-g_print("username %s\n",pwd->pw_name); | |
- addlen=9+strlen(pwd->pw_name); | |
+ if (NetBuf->socks->numuid) { | |
+ username=g_strdup_printf("%d",getuid()); | |
+ } else { | |
+ pwd = getpwuid(getuid()); | |
+ if (!pwd || !pwd->pw_name) return FALSE; | |
+ username=g_strdup(pwd->pw_name); | |
+ } | |
#endif | |
+ } | |
+ addlen=9+strlen(username); | |
haddr = (struct in_addr *)he->h_addr; | |
g_assert(sizeof(struct in_addr)==4); | |
t@@ -907,30 +900,18 @@ g_print("username %s\n",pwd->pw_name); | |
netport = htons(RemotePort); | |
g_assert(sizeof(netport)==2); | |
- addpt = ExpandWriteBuffer(conn,addlen); | |
- if (!addpt) { | |
- SetError(&NetBuf->error,ET_CUSTOM,E_FULLBUF,NULL); | |
- return FALSE; | |
- } | |
- | |
+ addpt = ExpandWriteBuffer(conn,addlen,&NetBuf->error); | |
+ if (!addpt) return FALSE; | |
addpt[0] = 4; /* SOCKS version */ | |
addpt[1] = 1; /* CONNECT */ | |
memcpy(&addpt[2],&netport,sizeof(netport)); | |
memcpy(&addpt[4],haddr,sizeof(struct in_addr)); | |
-#ifdef CYGWIN | |
strcpy(&addpt[8],username); | |
g_free(username); | |
-#else | |
- strcpy(&addpt[8],pwd->pw_name); | |
-#endif | |
addpt[addlen-1] = '\0'; | |
- conn->DataPresent+=addlen; | |
- | |
-/* If the buffer was empty before, we may need to tell the owner to check | |
- the socket for write-ready status */ | |
- if ((gchar *)addpt==conn->Data) NetBufCallBack(NetBuf); | |
+ CommitWriteBuffer(NetBuf,conn,addpt,addlen); | |
return TRUE; | |
} | |
t@@ -1094,7 +1075,7 @@ gboolean SetHttpAuthentication(HttpConnection *conn,gboo… | |
ptuser=&conn->user; ptpassword=&conn->password; | |
} | |
g_free(*ptuser); g_free(*ptpassword); | |
- if (user && password) { | |
+ if (user && password && user[0] && password[0]) { | |
*ptuser = g_strdup(user); | |
*ptpassword = g_strdup(password); | |
} else { | |
t@@ -1228,7 +1209,7 @@ gchar *ReadHttpResponse(HttpConnection *conn) { | |
gboolean HandleHttpCompletion(HttpConnection *conn) { | |
NBCallBack CallBack; | |
- gpointer CallBackData; | |
+ gpointer CallBackData,userpasswddata; | |
NBUserPasswd userpasswd; | |
gboolean retry=FALSE; | |
LastError **error; | |
t@@ -1266,12 +1247,14 @@ gboolean HandleHttpCompletion(HttpConnection *conn) { | |
if (retry) { | |
CallBack=conn->NetBuf.CallBack; | |
userpasswd=conn->NetBuf.userpasswd; | |
+ userpasswddata=conn->NetBuf.userpasswddata; | |
CallBackData=conn->NetBuf.CallBackData; | |
ShutdownNetworkBuffer(&conn->NetBuf); | |
if (StartHttpConnect(conn)) { | |
SendHttpRequest(conn); | |
SetNetworkBufferCallBack(&conn->NetBuf,CallBack,CallBackData); | |
- SetNetworkBufferUserPasswdFunc(&conn->NetBuf,userpasswd); | |
+ SetNetworkBufferUserPasswdFunc(&conn->NetBuf, | |
+ userpasswd,userpasswddata); | |
return FALSE; | |
} | |
} else if (conn->StatusCode>=300) { | |
t@@ -1323,10 +1306,11 @@ gboolean BindTCPSocket(int sock,unsigned port,LastErro… | |
} | |
gboolean StartConnect(int *fd,gchar *RemoteHost,unsigned RemotePort, | |
- gboolean NonBlocking,LastError **error) { | |
+ gboolean *doneOK,LastError **error) { | |
struct sockaddr_in ClientAddr; | |
struct hostent *he; | |
+ if (doneOK) *doneOK=FALSE; | |
he = LookupHostname(RemoteHost,error); | |
if (!he) return FALSE; | |
t@@ -1338,7 +1322,7 @@ gboolean StartConnect(int *fd,gchar *RemoteHost,unsigned… | |
ClientAddr.sin_addr=*((struct in_addr *)he->h_addr); | |
memset(ClientAddr.sin_zero,0,sizeof(ClientAddr.sin_zero)); | |
- SetBlocking(*fd,!NonBlocking); | |
+ SetBlocking(*fd,FALSE); | |
if (connect(*fd,(struct sockaddr *)&ClientAddr, | |
sizeof(struct sockaddr))==SOCKET_ERROR) { | |
t@@ -1353,7 +1337,7 @@ gboolean StartConnect(int *fd,gchar *RemoteHost,unsigned… | |
CloseSocket(*fd); *fd=-1; | |
return FALSE; | |
} else { | |
- SetBlocking(*fd,FALSE); /* All connected sockets should be nonblocking */ | |
+ if (doneOK) *doneOK=TRUE; | |
} | |
return TRUE; | |
} | |
diff --git a/src/network.h b/src/network.h | |
t@@ -65,7 +65,7 @@ typedef struct _NetworkBuffer NetworkBuffer; | |
typedef void (*NBCallBack)(NetworkBuffer *NetBuf,gboolean Read,gboolean Write); | |
-typedef void (*NBUserPasswd)(NetworkBuffer *NetBuf); | |
+typedef void (*NBUserPasswd)(NetworkBuffer *NetBuf,gpointer data); | |
/* Information about a SOCKS server */ | |
typedef struct _SocksServer { | |
t@@ -108,6 +108,7 @@ struct _NetworkBuffer { | |
SocksServer *socks; /* If non-NULL, a SOCKS server to use */ | |
NBUserPasswd userpasswd; /* Function to supply username and password for | |
SOCKS5 authentication */ | |
+ gpointer userpasswddata; /* data to pass to the above function */ | |
gchar *host; /* If non-NULL, the host to connect to */ | |
unsigned port; /* If non-NULL, the port to connect to */ | |
LastError *error; /* Any error from the last operation */ | |
t@@ -160,7 +161,7 @@ void InitNetworkBuffer(NetworkBuffer *NetBuf,char Terminat… | |
void SetNetworkBufferCallBack(NetworkBuffer *NetBuf,NBCallBack CallBack, | |
gpointer CallBackData); | |
void SetNetworkBufferUserPasswdFunc(NetworkBuffer *NetBuf, | |
- NBUserPasswd userpasswd); | |
+ NBUserPasswd userpasswd,gpointer data); | |
gboolean IsNetworkBufferActive(NetworkBuffer *NetBuf); | |
void BindNetworkBufferToSocket(NetworkBuffer *NetBuf,int fd); | |
gboolean StartNetworkBufferConnect(NetworkBuffer *NetBuf,gchar *RemoteHost, | |
t@@ -180,6 +181,11 @@ gint CountWaitingMessages(NetworkBuffer *NetBuf); | |
gchar *GetWaitingMessage(NetworkBuffer *NetBuf); | |
gboolean SendSocks5UserPasswd(NetworkBuffer *NetBuf,gchar *user, | |
gchar *password); | |
+gchar *GetWaitingData(NetworkBuffer *NetBuf,int numbytes); | |
+gchar *PeekWaitingData(NetworkBuffer *NetBuf,int numbytes); | |
+gchar *ExpandWriteBuffer(ConnBuf *conn,int numbytes,LastError **error); | |
+void CommitWriteBuffer(NetworkBuffer *NetBuf,ConnBuf *conn, | |
+ gchar *addpt,guint addlen); | |
gboolean OpenHttpConnection(HttpConnection **conn,gchar *HostName, | |
unsigned Port,gchar *Proxy,unsigned ProxyPort, | |
t@@ -196,8 +202,6 @@ gboolean IsHttpError(HttpConnection *conn); | |
int CreateTCPSocket(LastError **error); | |
gboolean BindTCPSocket(int sock,unsigned port,LastError **error); | |
-gboolean StartConnect(int *fd,gchar *RemoteHost,unsigned RemotePort, | |
- gboolean NonBlocking,LastError **error); | |
void StartNetworking(void); | |
void StopNetworking(void); | |
diff --git a/src/serverside.c b/src/serverside.c | |
t@@ -138,6 +138,7 @@ static void MetaSocketStatus(NetworkBuffer *NetBuf, | |
gboolean Read,gboolean Write); | |
#endif | |
+#ifdef NETWORKING | |
static gboolean MetaConnectError(HttpConnection *conn) { | |
GString *errstr; | |
if (!IsHttpError(conn)) return FALSE; | |
t@@ -148,6 +149,7 @@ static gboolean MetaConnectError(HttpConnection *conn) { | |
g_string_free(errstr,TRUE); | |
return TRUE; | |
} | |
+#endif | |
void RegisterWithMetaServer(gboolean Up,gboolean SendData, | |
gboolean RespectTimeout) { | |
t@@ -808,7 +810,6 @@ Player *HandleNewConnection(void) { | |
&cadsize))==-1) { | |
perror("accept socket"); bgetch(); exit(1); | |
} | |
- SetBlocking(ClientSock,FALSE); | |
dopelog(2,_("got connection from %s"),inet_ntoa(ClientAddr.sin_addr)); | |
tmp=g_new(Player,1); | |
FirstServer=AddPlayer(ClientSock,tmp,FirstServer); |