Fossil SCM
Added the --sshtrace command-line option that provides diagnostic output on the connection setup for all SSH sync traffic. Make the SSH connection setup pause waiting for responses, if the desired response is not obtained right away.
Commit
00cf858afe7ab65ea4eaa578f6fedad29e40c114
Parent
4473a27f3b6e049…
2 files changed
+64
-21
+2
+64
-21
| --- src/http_transport.c | ||
| +++ src/http_transport.c | ||
| @@ -97,10 +97,73 @@ | ||
| 97 | 97 | #ifdef __MINGW32__ |
| 98 | 98 | static char zDefaultSshCmd[] = "ssh -T"; |
| 99 | 99 | #else |
| 100 | 100 | static char zDefaultSshCmd[] = "ssh -e none -T"; |
| 101 | 101 | #endif |
| 102 | + | |
| 103 | +/* | |
| 104 | +** Bring up an SSH link. This involves sending some "echo" commands and | |
| 105 | +** get back appropriate responses. The point is to move past the MOTD and | |
| 106 | +** verify that the link is working. | |
| 107 | +*/ | |
| 108 | +static void transport_ssh_startup(void){ | |
| 109 | + char *zIn; /* An input line received back from remote */ | |
| 110 | + int nWait; /* Number of times waiting for the MOTD */ | |
| 111 | + unsigned iRandom; /* Random probe value */ | |
| 112 | + char zProbe[30]; /* Text of the random probe */ | |
| 113 | + int nProbe; /* Size of probe message */ | |
| 114 | + int nIn; /* Size of input */ | |
| 115 | + static const int nBuf = 10000; /* Size of input buffer */ | |
| 116 | + | |
| 117 | + zIn = fossil_malloc(nBuf); | |
| 118 | + sqlite3_randomness(sizeof(iRandom), &iRandom); | |
| 119 | + sqlite3_snprintf(sizeof(zProbe), zProbe, "probe-%08x", iRandom); | |
| 120 | + nProbe = (int)strlen(zProbe); | |
| 121 | + fprintf(sshOut, "echo %s\n", zProbe); | |
| 122 | + fflush(sshOut); | |
| 123 | + if( g.fSshTrace ){ | |
| 124 | + printf("Sent: [echo %s]\n", zProbe); | |
| 125 | + fflush(stdout); | |
| 126 | + } | |
| 127 | + memset(zIn, '*', nProbe); | |
| 128 | + for(nWait=1; nWait<=10; nWait++){ | |
| 129 | + sshin_read(zIn+nProbe, nBuf-nProbe); | |
| 130 | + if( g.fSshTrace ){ | |
| 131 | + printf("Got back-----------------------------------------------\n" | |
| 132 | + "%s\n" | |
| 133 | + "-------------------------------------------------------\n", | |
| 134 | + zIn+nProbe); | |
| 135 | + } | |
| 136 | + if( strstr(zIn, zProbe) ) break; | |
| 137 | + sqlite3_sleep(100*nWait); | |
| 138 | + nIn = (int)strlen(zIn); | |
| 139 | + memcpy(zIn, zIn+(nIn-nProbe), nProbe); | |
| 140 | + if( g.fSshTrace ){ | |
| 141 | + printf("Fetching more text. Looking for [%s]...\n", zProbe); | |
| 142 | + fflush(stdout); | |
| 143 | + } | |
| 144 | + } | |
| 145 | + sqlite3_randomness(sizeof(iRandom), &iRandom); | |
| 146 | + sqlite3_snprintf(sizeof(zProbe), zProbe, "probe-%08x", iRandom); | |
| 147 | + fprintf(sshOut, "echo %s\n", zProbe); | |
| 148 | + fflush(sshOut); | |
| 149 | + if( g.fSshTrace ){ | |
| 150 | + printf("Sent: [echo %s]\n", zProbe); | |
| 151 | + fflush(stdout); | |
| 152 | + } | |
| 153 | + sshin_read(zIn, nBuf); | |
| 154 | + if( g.fSshTrace ){ | |
| 155 | + printf("Got back-----------------------------------------------\n" | |
| 156 | + "%s\n" | |
| 157 | + "-------------------------------------------------------\n", zIn); | |
| 158 | + } | |
| 159 | + if( memcmp(zIn, zProbe, nProbe)!=0 ){ | |
| 160 | + pclose2(sshIn, sshOut, sshPid); | |
| 161 | + fossil_fatal("ssh connection failed: [%s]", zIn); | |
| 162 | + } | |
| 163 | + fossil_free(zIn); | |
| 164 | +} | |
| 102 | 165 | |
| 103 | 166 | /* |
| 104 | 167 | ** Global initialization of the transport layer |
| 105 | 168 | */ |
| 106 | 169 | void transport_global_startup(void){ |
| @@ -109,13 +172,10 @@ | ||
| 109 | 172 | ** and run an SSH command to talk to the remote machine. |
| 110 | 173 | */ |
| 111 | 174 | const char *zSsh; /* The base SSH command */ |
| 112 | 175 | Blob zCmd; /* The SSH command */ |
| 113 | 176 | char *zHost; /* The host name to contact */ |
| 114 | - char *zIn; /* An input line received back from remote */ | |
| 115 | - unsigned iRandom; | |
| 116 | - char zProbe[30]; | |
| 117 | 177 | |
| 118 | 178 | zSsh = db_get("ssh-command", zDefaultSshCmd); |
| 119 | 179 | blob_init(&zCmd, zSsh, -1); |
| 120 | 180 | if( g.urlPort!=g.urlDfltPort ){ |
| 121 | 181 | #ifdef __MINGW32__ |
| @@ -156,28 +216,11 @@ | ||
| 156 | 216 | popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid); |
| 157 | 217 | if( sshPid==0 ){ |
| 158 | 218 | fossil_fatal("cannot start ssh tunnel using [%b]", &zCmd); |
| 159 | 219 | } |
| 160 | 220 | blob_reset(&zCmd); |
| 161 | - | |
| 162 | - /* Send a couple of "echo" command to the other side to make sure that the | |
| 163 | - ** connection is up and working. | |
| 164 | - */ | |
| 165 | - fprintf(sshOut, "echo test1\n"); | |
| 166 | - fflush(sshOut); | |
| 167 | - zIn = fossil_malloc(50000); | |
| 168 | - sshin_read(zIn, 50000); | |
| 169 | - sqlite3_randomness(sizeof(iRandom), &iRandom); | |
| 170 | - sqlite3_snprintf(sizeof(zProbe), zProbe, "probe-%08x", iRandom); | |
| 171 | - fprintf(sshOut, "echo %s\n", zProbe); | |
| 172 | - fflush(sshOut); | |
| 173 | - sshin_read(zIn, 500); | |
| 174 | - if( memcmp(zIn, zProbe, 14)!=0 ){ | |
| 175 | - pclose2(sshIn, sshOut, sshPid); | |
| 176 | - fossil_fatal("ssh connection failed: [%s]", zIn); | |
| 177 | - } | |
| 178 | - fossil_free(zIn); | |
| 221 | + transport_ssh_startup(); | |
| 179 | 222 | } |
| 180 | 223 | } |
| 181 | 224 | |
| 182 | 225 | /* |
| 183 | 226 | ** Open a connection to the server. The server is defined by the following |
| 184 | 227 |
| --- src/http_transport.c | |
| +++ src/http_transport.c | |
| @@ -97,10 +97,73 @@ | |
| 97 | #ifdef __MINGW32__ |
| 98 | static char zDefaultSshCmd[] = "ssh -T"; |
| 99 | #else |
| 100 | static char zDefaultSshCmd[] = "ssh -e none -T"; |
| 101 | #endif |
| 102 | |
| 103 | /* |
| 104 | ** Global initialization of the transport layer |
| 105 | */ |
| 106 | void transport_global_startup(void){ |
| @@ -109,13 +172,10 @@ | |
| 109 | ** and run an SSH command to talk to the remote machine. |
| 110 | */ |
| 111 | const char *zSsh; /* The base SSH command */ |
| 112 | Blob zCmd; /* The SSH command */ |
| 113 | char *zHost; /* The host name to contact */ |
| 114 | char *zIn; /* An input line received back from remote */ |
| 115 | unsigned iRandom; |
| 116 | char zProbe[30]; |
| 117 | |
| 118 | zSsh = db_get("ssh-command", zDefaultSshCmd); |
| 119 | blob_init(&zCmd, zSsh, -1); |
| 120 | if( g.urlPort!=g.urlDfltPort ){ |
| 121 | #ifdef __MINGW32__ |
| @@ -156,28 +216,11 @@ | |
| 156 | popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid); |
| 157 | if( sshPid==0 ){ |
| 158 | fossil_fatal("cannot start ssh tunnel using [%b]", &zCmd); |
| 159 | } |
| 160 | blob_reset(&zCmd); |
| 161 | |
| 162 | /* Send a couple of "echo" command to the other side to make sure that the |
| 163 | ** connection is up and working. |
| 164 | */ |
| 165 | fprintf(sshOut, "echo test1\n"); |
| 166 | fflush(sshOut); |
| 167 | zIn = fossil_malloc(50000); |
| 168 | sshin_read(zIn, 50000); |
| 169 | sqlite3_randomness(sizeof(iRandom), &iRandom); |
| 170 | sqlite3_snprintf(sizeof(zProbe), zProbe, "probe-%08x", iRandom); |
| 171 | fprintf(sshOut, "echo %s\n", zProbe); |
| 172 | fflush(sshOut); |
| 173 | sshin_read(zIn, 500); |
| 174 | if( memcmp(zIn, zProbe, 14)!=0 ){ |
| 175 | pclose2(sshIn, sshOut, sshPid); |
| 176 | fossil_fatal("ssh connection failed: [%s]", zIn); |
| 177 | } |
| 178 | fossil_free(zIn); |
| 179 | } |
| 180 | } |
| 181 | |
| 182 | /* |
| 183 | ** Open a connection to the server. The server is defined by the following |
| 184 |
| --- src/http_transport.c | |
| +++ src/http_transport.c | |
| @@ -97,10 +97,73 @@ | |
| 97 | #ifdef __MINGW32__ |
| 98 | static char zDefaultSshCmd[] = "ssh -T"; |
| 99 | #else |
| 100 | static char zDefaultSshCmd[] = "ssh -e none -T"; |
| 101 | #endif |
| 102 | |
| 103 | /* |
| 104 | ** Bring up an SSH link. This involves sending some "echo" commands and |
| 105 | ** get back appropriate responses. The point is to move past the MOTD and |
| 106 | ** verify that the link is working. |
| 107 | */ |
| 108 | static void transport_ssh_startup(void){ |
| 109 | char *zIn; /* An input line received back from remote */ |
| 110 | int nWait; /* Number of times waiting for the MOTD */ |
| 111 | unsigned iRandom; /* Random probe value */ |
| 112 | char zProbe[30]; /* Text of the random probe */ |
| 113 | int nProbe; /* Size of probe message */ |
| 114 | int nIn; /* Size of input */ |
| 115 | static const int nBuf = 10000; /* Size of input buffer */ |
| 116 | |
| 117 | zIn = fossil_malloc(nBuf); |
| 118 | sqlite3_randomness(sizeof(iRandom), &iRandom); |
| 119 | sqlite3_snprintf(sizeof(zProbe), zProbe, "probe-%08x", iRandom); |
| 120 | nProbe = (int)strlen(zProbe); |
| 121 | fprintf(sshOut, "echo %s\n", zProbe); |
| 122 | fflush(sshOut); |
| 123 | if( g.fSshTrace ){ |
| 124 | printf("Sent: [echo %s]\n", zProbe); |
| 125 | fflush(stdout); |
| 126 | } |
| 127 | memset(zIn, '*', nProbe); |
| 128 | for(nWait=1; nWait<=10; nWait++){ |
| 129 | sshin_read(zIn+nProbe, nBuf-nProbe); |
| 130 | if( g.fSshTrace ){ |
| 131 | printf("Got back-----------------------------------------------\n" |
| 132 | "%s\n" |
| 133 | "-------------------------------------------------------\n", |
| 134 | zIn+nProbe); |
| 135 | } |
| 136 | if( strstr(zIn, zProbe) ) break; |
| 137 | sqlite3_sleep(100*nWait); |
| 138 | nIn = (int)strlen(zIn); |
| 139 | memcpy(zIn, zIn+(nIn-nProbe), nProbe); |
| 140 | if( g.fSshTrace ){ |
| 141 | printf("Fetching more text. Looking for [%s]...\n", zProbe); |
| 142 | fflush(stdout); |
| 143 | } |
| 144 | } |
| 145 | sqlite3_randomness(sizeof(iRandom), &iRandom); |
| 146 | sqlite3_snprintf(sizeof(zProbe), zProbe, "probe-%08x", iRandom); |
| 147 | fprintf(sshOut, "echo %s\n", zProbe); |
| 148 | fflush(sshOut); |
| 149 | if( g.fSshTrace ){ |
| 150 | printf("Sent: [echo %s]\n", zProbe); |
| 151 | fflush(stdout); |
| 152 | } |
| 153 | sshin_read(zIn, nBuf); |
| 154 | if( g.fSshTrace ){ |
| 155 | printf("Got back-----------------------------------------------\n" |
| 156 | "%s\n" |
| 157 | "-------------------------------------------------------\n", zIn); |
| 158 | } |
| 159 | if( memcmp(zIn, zProbe, nProbe)!=0 ){ |
| 160 | pclose2(sshIn, sshOut, sshPid); |
| 161 | fossil_fatal("ssh connection failed: [%s]", zIn); |
| 162 | } |
| 163 | fossil_free(zIn); |
| 164 | } |
| 165 | |
| 166 | /* |
| 167 | ** Global initialization of the transport layer |
| 168 | */ |
| 169 | void transport_global_startup(void){ |
| @@ -109,13 +172,10 @@ | |
| 172 | ** and run an SSH command to talk to the remote machine. |
| 173 | */ |
| 174 | const char *zSsh; /* The base SSH command */ |
| 175 | Blob zCmd; /* The SSH command */ |
| 176 | char *zHost; /* The host name to contact */ |
| 177 | |
| 178 | zSsh = db_get("ssh-command", zDefaultSshCmd); |
| 179 | blob_init(&zCmd, zSsh, -1); |
| 180 | if( g.urlPort!=g.urlDfltPort ){ |
| 181 | #ifdef __MINGW32__ |
| @@ -156,28 +216,11 @@ | |
| 216 | popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid); |
| 217 | if( sshPid==0 ){ |
| 218 | fossil_fatal("cannot start ssh tunnel using [%b]", &zCmd); |
| 219 | } |
| 220 | blob_reset(&zCmd); |
| 221 | transport_ssh_startup(); |
| 222 | } |
| 223 | } |
| 224 | |
| 225 | /* |
| 226 | ** Open a connection to the server. The server is defined by the following |
| 227 |
+2
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -129,10 +129,11 @@ | ||
| 129 | 129 | int fSqlStats; /* True if --sqltrace or --sqlstats are present */ |
| 130 | 130 | int fSqlPrint; /* True if -sqlprint flag is present */ |
| 131 | 131 | int fQuiet; /* True if -quiet flag is present */ |
| 132 | 132 | int fHttpTrace; /* Trace outbound HTTP requests */ |
| 133 | 133 | int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */ |
| 134 | + int fSshTrace; /* Trace the SSH setup traffic */ | |
| 134 | 135 | int fNoSync; /* Do not do an autosync even. --nosync */ |
| 135 | 136 | char *zPath; /* Name of webpage being served */ |
| 136 | 137 | char *zExtra; /* Extra path information past the webpage name */ |
| 137 | 138 | char *zBaseURL; /* Full text of the URL being served */ |
| 138 | 139 | char *zTop; /* Parent directory of zPath */ |
| @@ -611,10 +612,11 @@ | ||
| 611 | 612 | g.isHTTP = 0; |
| 612 | 613 | g.fQuiet = find_option("quiet", 0, 0)!=0; |
| 613 | 614 | g.fSqlTrace = find_option("sqltrace", 0, 0)!=0; |
| 614 | 615 | g.fSqlStats = find_option("sqlstats", 0, 0)!=0; |
| 615 | 616 | g.fSystemTrace = find_option("systemtrace", 0, 0)!=0; |
| 617 | + g.fSshTrace = find_option("sshtrace", 0, 0)!=0; | |
| 616 | 618 | if( g.fSqlTrace ) g.fSqlStats = 1; |
| 617 | 619 | g.fSqlPrint = find_option("sqlprint", 0, 0)!=0; |
| 618 | 620 | g.fHttpTrace = find_option("httptrace", 0, 0)!=0; |
| 619 | 621 | g.zLogin = find_option("user", "U", 1); |
| 620 | 622 | g.zSSLIdentity = find_option("ssl-identity", 0, 1); |
| 621 | 623 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -129,10 +129,11 @@ | |
| 129 | int fSqlStats; /* True if --sqltrace or --sqlstats are present */ |
| 130 | int fSqlPrint; /* True if -sqlprint flag is present */ |
| 131 | int fQuiet; /* True if -quiet flag is present */ |
| 132 | int fHttpTrace; /* Trace outbound HTTP requests */ |
| 133 | int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */ |
| 134 | int fNoSync; /* Do not do an autosync even. --nosync */ |
| 135 | char *zPath; /* Name of webpage being served */ |
| 136 | char *zExtra; /* Extra path information past the webpage name */ |
| 137 | char *zBaseURL; /* Full text of the URL being served */ |
| 138 | char *zTop; /* Parent directory of zPath */ |
| @@ -611,10 +612,11 @@ | |
| 611 | g.isHTTP = 0; |
| 612 | g.fQuiet = find_option("quiet", 0, 0)!=0; |
| 613 | g.fSqlTrace = find_option("sqltrace", 0, 0)!=0; |
| 614 | g.fSqlStats = find_option("sqlstats", 0, 0)!=0; |
| 615 | g.fSystemTrace = find_option("systemtrace", 0, 0)!=0; |
| 616 | if( g.fSqlTrace ) g.fSqlStats = 1; |
| 617 | g.fSqlPrint = find_option("sqlprint", 0, 0)!=0; |
| 618 | g.fHttpTrace = find_option("httptrace", 0, 0)!=0; |
| 619 | g.zLogin = find_option("user", "U", 1); |
| 620 | g.zSSLIdentity = find_option("ssl-identity", 0, 1); |
| 621 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -129,10 +129,11 @@ | |
| 129 | int fSqlStats; /* True if --sqltrace or --sqlstats are present */ |
| 130 | int fSqlPrint; /* True if -sqlprint flag is present */ |
| 131 | int fQuiet; /* True if -quiet flag is present */ |
| 132 | int fHttpTrace; /* Trace outbound HTTP requests */ |
| 133 | int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */ |
| 134 | int fSshTrace; /* Trace the SSH setup traffic */ |
| 135 | int fNoSync; /* Do not do an autosync even. --nosync */ |
| 136 | char *zPath; /* Name of webpage being served */ |
| 137 | char *zExtra; /* Extra path information past the webpage name */ |
| 138 | char *zBaseURL; /* Full text of the URL being served */ |
| 139 | char *zTop; /* Parent directory of zPath */ |
| @@ -611,10 +612,11 @@ | |
| 612 | g.isHTTP = 0; |
| 613 | g.fQuiet = find_option("quiet", 0, 0)!=0; |
| 614 | g.fSqlTrace = find_option("sqltrace", 0, 0)!=0; |
| 615 | g.fSqlStats = find_option("sqlstats", 0, 0)!=0; |
| 616 | g.fSystemTrace = find_option("systemtrace", 0, 0)!=0; |
| 617 | g.fSshTrace = find_option("sshtrace", 0, 0)!=0; |
| 618 | if( g.fSqlTrace ) g.fSqlStats = 1; |
| 619 | g.fSqlPrint = find_option("sqlprint", 0, 0)!=0; |
| 620 | g.fHttpTrace = find_option("httptrace", 0, 0)!=0; |
| 621 | g.zLogin = find_option("user", "U", 1); |
| 622 | g.zSSLIdentity = find_option("ssl-identity", 0, 1); |
| 623 |