Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Change the "ui" and "sshd" commands so that they bind to INADDR_LOOPBACK rather than INADDR_ANY. Disable the "quit" monitoring on "ui" and "server". Add better error messages explaining that ssh:// is not yet supported on windows. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | experimental |
| Files: | files | file ages | folders |
| SHA1: |
2f8e4c4b382a357d79028fef34b008c5 |
| User & Date: | drh 2010-08-25 19:55:40.000 |
Context
|
2010-08-26
| ||
| 02:32 | A rework of the SSH sync method that does not use TCP port forwarding. It works in some cases but not other. The failure is probably do to I/O buffering issues. Need further work. ... (check-in: 192ceef3ca user: drh tags: experimental) | |
|
2010-08-25
| ||
| 20:00 | Merge the ssh:// sync enhancement into the trunk. ... (check-in: 0e42cc1b77 user: drh tags: trunk) | |
| 19:55 | Change the "ui" and "sshd" commands so that they bind to INADDR_LOOPBACK rather than INADDR_ANY. Disable the "quit" monitoring on "ui" and "server". Add better error messages explaining that ssh:// is not yet supported on windows. ... (check-in: 2f8e4c4b38 user: drh tags: experimental) | |
| 17:00 | The ssh:// sync method appears to work now, for linux-to-linux... ... (check-in: 66cdaee68e user: drh tags: experimental) | |
Changes
Changes to src/cgi.c.
| ︙ | ︙ | |||
1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 |
if( g.zAccessToken && !accessTokenSeen ){
forbidden_request();
}
cgi_init();
}
/*
** Maximum number of child processes that we can have running
** at one time before we start slowing things down.
*/
#define MAX_PARALLEL 2
/*
** Implement an HTTP server daemon listening on port iPort.
**
** As new connections arrive, fork a child and let child return
** out of this procedure call. The child will handle the request.
** The parent never returns from this procedure.
**
** Return 0 to each child as it runs. If unable to establish a
** listening socket, return non-zero.
*/
| > > > > > > > > > | > > > | > | 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 |
if( g.zAccessToken && !accessTokenSeen ){
forbidden_request();
}
cgi_init();
}
#if INTERFACE
/*
** Bitmap values for the flags parameter to cgi_http_server().
*/
#define HTTP_SERVER_LOCALHOST 0x0001 /* Bind to 127.0.0.1 only */
#define HTTP_SERVER_STDIN 0x0002 /* Monitor stdin for "quit" */
#endif /* INTERFACE */
/*
** Maximum number of child processes that we can have running
** at one time before we start slowing things down.
*/
#define MAX_PARALLEL 2
/*
** Implement an HTTP server daemon listening on port iPort.
**
** As new connections arrive, fork a child and let child return
** out of this procedure call. The child will handle the request.
** The parent never returns from this procedure.
**
** Return 0 to each child as it runs. If unable to establish a
** listening socket, return non-zero.
*/
int cgi_http_server(int mnPort, int mxPort, char *zBrowser, int flags){
#ifdef __MINGW32__
/* Use win32_http_server() instead */
fossil_exit(1);
#else
int listener = -1; /* The server socket */
int connection; /* A socket for each individual connection */
fd_set readfds; /* Set of file descriptors for select() */
size_t lenaddr; /* Length of the inaddr structure */
int child; /* PID of the child process */
int nchildren = 0; /* Number of child processes */
struct timeval delay; /* How long to wait inside select() */
struct sockaddr_in inaddr; /* The socket address */
int opt = 1; /* setsockopt flag */
int iPort = mnPort;
while( iPort<=mxPort ){
memset(&inaddr, 0, sizeof(inaddr));
inaddr.sin_family = AF_INET;
if( flags & HTTP_SERVER_LOCALHOST ){
inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
}else{
inaddr.sin_addr.s_addr = htonl(INADDR_ANY);
}
inaddr.sin_port = htons(iPort);
listener = socket(AF_INET, SOCK_STREAM, 0);
if( listener<0 ){
iPort++;
continue;
}
|
| ︙ | ︙ | |||
1250 1251 1252 1253 1254 1255 1256 |
/* Slow down if connections are arriving too fast */
sleep( nchildren-MAX_PARALLEL );
}
delay.tv_sec = 60;
delay.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET( listener, &readfds);
| > | > > | 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 |
/* Slow down if connections are arriving too fast */
sleep( nchildren-MAX_PARALLEL );
}
delay.tv_sec = 60;
delay.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET( listener, &readfds);
if( flags & HTTP_SERVER_STDIN ){
FD_SET( 0, &readfds);
}
select( listener+1, &readfds, 0, 0, &delay);
if( FD_ISSET(0, &readfds) ){
int i;
char zIn[200];
assert( flags & HTTP_SERVER_STDIN );
zIn[0] = 0;
fgets(zIn, sizeof(zIn), stdin);
for(i=0; zIn[i] && zIn[i]!='\n'; i++){}
zIn[i] = 0;
if( strcmp(zIn, "quit")==0 || feof(stdin) ) fossil_exit(0);
}
if( FD_ISSET(listener, &readfds) ){
|
| ︙ | ︙ |
Changes to src/http_transport.c.
| ︙ | ︙ | |||
70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
** Global initialization of the transport layer
*/
void transport_global_startup(void){
if( g.urlIsSsh ){
char *zCmd;
int i;
char zIn[200];
if( g.urlUser && g.urlUser[0] ){
zCmd = mprintf(
"ssh -L127.0.0.1:%d:127.0.0.1:%d %s@%s "
"\"fossil server -P %d '%s'\"",
g.urlPort, g.urlPort, g.urlUser, g.urlSshHost, g.urlPort, g.urlPath
);
}else{
| > > > | 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
** Global initialization of the transport layer
*/
void transport_global_startup(void){
if( g.urlIsSsh ){
char *zCmd;
int i;
char zIn[200];
#ifdef __MINGW32__
fossil_fatal("the ssh:// sync method is currently only supported on unix");
#endif
if( g.urlUser && g.urlUser[0] ){
zCmd = mprintf(
"ssh -L127.0.0.1:%d:127.0.0.1:%d %s@%s "
"\"fossil server -P %d '%s'\"",
g.urlPort, g.urlPort, g.urlUser, g.urlSshHost, g.urlPort, g.urlPath
);
}else{
|
| ︙ | ︙ | |||
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 |
}
/* printf("Got line: [%s]\n", &transport.pBuf[iStart]); */
return &transport.pBuf[iStart];
}
void transport_global_shutdown(void){
if( g.urlIsSsh && g.sshPid ){
pclose2(g.sshIn, g.sshOut, g.sshPid);
g.sshPid = 0;
}
if( g.urlIsHttps ){
#ifdef FOSSIL_ENABLE_SSL
ssl_global_shutdown();
#endif
}else{
socket_global_shutdown();
}
}
| > > | 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 |
}
/* printf("Got line: [%s]\n", &transport.pBuf[iStart]); */
return &transport.pBuf[iStart];
}
void transport_global_shutdown(void){
if( g.urlIsSsh && g.sshPid ){
printf("Closing SSH tunnel: ");
fflush(stdout);
pclose2(g.sshIn, g.sshOut, g.sshPid);
g.sshPid = 0;
}
if( g.urlIsHttps ){
#ifdef FOSSIL_ENABLE_SSL
ssl_global_shutdown();
#endif
}else{
socket_global_shutdown();
}
}
|
Changes to src/main.c.
| ︙ | ︙ | |||
988 989 990 991 992 993 994 | ** Open a socket and begin listening and responding to HTTP requests on ** TCP port 8080, or on any other TCP port defined by the -P or ** --port option. The optional argument is the name of the repository. ** The repository argument may be omitted if the working directory is ** within an open checkout. ** ** The "ui" command automatically starts a web browser after initializing | | > > > > > > > > > > > > > | 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 |
** Open a socket and begin listening and responding to HTTP requests on
** TCP port 8080, or on any other TCP port defined by the -P or
** --port option. The optional argument is the name of the repository.
** The repository argument may be omitted if the working directory is
** within an open checkout.
**
** The "ui" command automatically starts a web browser after initializing
** the web server. The "ui" command also binds to 127.0.0.1 and so will
** only process HTTP traffic from the local machine.
**
** In the "server" command, the REPOSITORY can be a directory (aka folder)
** that contains one or more respositories with names ending in ".fossil".
** In that case, the first element of the URL is used to select among the
** various repositories.
**
** The "ui" or "server" verb can also be "sshd". This is used internally
** by the ssh:// sync method.
*/
void cmd_webserver(void){
int iPort, mxPort; /* Range of TCP ports allowed */
const char *zPort; /* Value of the --port option */
char *zBrowser; /* Name of web browser program */
char *zBrowserCmd = 0; /* Command to launch the web browser */
int isUiCmd; /* True if command is "ui", not "server' */
const char *zNotFound; /* The --notfound option or NULL */
int flags = 0; /* Server flags */
#ifdef __MINGW32__
const char *zStopperFile; /* Name of file used to terminate server */
zStopperFile = find_option("stopper", 0, 1);
#endif
g.thTrace = find_option("th-trace", 0, 0)!=0;
if( g.thTrace ){
blob_zero(&g.thLog);
}
zPort = find_option("port", "P", 1);
zNotFound = find_option("notfound", 0, 1);
if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
isUiCmd = g.argv[1][0]=='u';
if( isUiCmd ) flags |= HTTP_SERVER_LOCALHOST;
find_server_repository(isUiCmd);
if( zPort ){
iPort = mxPort = atoi(zPort);
}else{
iPort = db_get_int("http-port", 8080);
mxPort = iPort+100;
}
if( g.argv[1][0]=='s' && g.argv[1][1]=='s' ){
/* For ssh://, output a random "access token" that must appear in
** the header of every HTTP request. HTTP requests without the
** correct access token reply with 403 Forbidden. The access token
** prevents any clients other than the one client that launched the
** remote server via SSH from accessing the remote server.
*/
g.zAccessToken = db_text(0, "SELECT lower(hex(randomblob(20)))");
printf("Access-Token: %s\n", g.zAccessToken);
fflush(stdout);
flags |= HTTP_SERVER_LOCALHOST | HTTP_SERVER_STDIN;
}
#ifndef __MINGW32__
/* Unix implementation */
if( isUiCmd ){
#if !defined(__DARWIN__) && !defined(__APPLE__)
zBrowser = db_get("web-browser", 0);
if( zBrowser==0 ){
|
| ︙ | ︙ | |||
1050 1051 1052 1053 1054 1055 1056 |
}
#else
zBrowser = db_get("web-browser", "open");
#endif
zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
}
db_close();
| | | | 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 |
}
#else
zBrowser = db_get("web-browser", "open");
#endif
zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
}
db_close();
if( cgi_http_server(iPort, mxPort, zBrowserCmd, flags) ){
fossil_fatal("unable to listen on TCP socket %d", iPort);
}
g.httpIn = stdin;
g.httpOut = stdout;
if( g.fHttpTrace || g.fSqlTrace ){
fprintf(stderr, "====== SERVER pid %d =======\n", getpid());
}
g.cgiOutput = 1;
find_server_repository(isUiCmd);
g.zRepositoryName = enter_chroot_jail(g.zRepositoryName);
cgi_handle_http_request(0);
process_one_web_page(zNotFound);
#else
/* Win32 implementation */
if( isUiCmd ){
zBrowser = db_get("web-browser", "start");
zBrowserCmd = mprintf("%s http://127.0.0.1:%%d/", zBrowser);
}
db_close();
win32_http_server(iPort, mxPort, zBrowserCmd, zStopperFile, zNotFound, flags);
#endif
}
|
Changes to src/winhttp.c.
| ︙ | ︙ | |||
131 132 133 134 135 136 137 | ** Start a listening socket and process incoming HTTP requests on ** that socket. */ void win32_http_server( int mnPort, int mxPort, /* Range of allowed TCP port numbers */ const char *zBrowser, /* Command to launch browser. (Or NULL) */ const char *zStopper, /* Stop server when this file is exists (Or NULL) */ | | > | 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
** Start a listening socket and process incoming HTTP requests on
** that socket.
*/
void win32_http_server(
int mnPort, int mxPort, /* Range of allowed TCP port numbers */
const char *zBrowser, /* Command to launch browser. (Or NULL) */
const char *zStopper, /* Stop server when this file is exists (Or NULL) */
const char *zNotFound, /* The --notfound option, or NULL */
int flags /* One or more HTTP_SERVER_ flags */
){
WSADATA wd;
SOCKET s = INVALID_SOCKET;
SOCKADDR_IN addr;
int idCnt = 0;
int iPort = mnPort;
char *zNotFoundOption;
|
| ︙ | ︙ | |||
156 157 158 159 160 161 162 |
while( iPort<=mxPort ){
s = socket(AF_INET, SOCK_STREAM, 0);
if( s==INVALID_SOCKET ){
fossil_fatal("unable to create a socket");
}
addr.sin_family = AF_INET;
addr.sin_port = htons(iPort);
| > > > | > | 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
while( iPort<=mxPort ){
s = socket(AF_INET, SOCK_STREAM, 0);
if( s==INVALID_SOCKET ){
fossil_fatal("unable to create a socket");
}
addr.sin_family = AF_INET;
addr.sin_port = htons(iPort);
if( flags & HTTP_SERVER_LOCALHOST ){
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
}else{
addr.sin_addr.s_addr = htonl(INADDR_ANY);
}
if( bind(s, (struct sockaddr*)&addr, sizeof(addr))==SOCKET_ERROR ){
closesocket(s);
iPort++;
continue;
}
if( listen(s, SOMAXCONN)==SOCKET_ERROR ){
closesocket(s);
|
| ︙ | ︙ |