Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Refactor the HTTP client logic to make it much easier to add support for "file:" and "https:" URLs on push, pull, sync, and clone. |
|---|---|
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA1: |
737e76a69fbc2e8327195198d14a9287 |
| User & Date: | drh 2009-03-30 00:31:56.000 |
References
|
2009-04-13
| ||
| 18:00 | • Ticket [9a42dd09e0] fossil pull has to be run multiple times status still Open with 1 other change artifact: ae9630e0f8 user: eric | |
| 15:59 | • Ticket [9a42dd09e0]: 1 change artifact: 07a3500705 user: drh | |
Context
|
2009-03-30
| ||
| 00:58 | Continuing work on the new HTTP transport mechanism. Make it more obvious where in the code extensions to support file: and https: belong. check-in: 327823e39b user: drh tags: trunk | |
| 00:31 | Refactor the HTTP client logic to make it much easier to add support for "file:" and "https:" URLs on push, pull, sync, and clone. check-in: 737e76a69f user: drh tags: trunk | |
|
2009-03-29
| ||
| 22:24 | Use "no-store" in place of "private" as the cache-control mode. Ticket [b465b3bc2ceef4446b2ae770242ed0968e4dbc68]. check-in: 5ffc720194 user: drh tags: trunk | |
Changes
Changes to src/http.c.
| ︙ | ︙ | |||
21 22 23 24 25 26 27 | ** ******************************************************************************* ** ** This file contains code that implements the client-side HTTP protocol */ #include "config.h" #include "http.h" | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < | | < < < < > | > > > > | < | | < < < > > | | | < | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < < < < < | < < < < < < < < > | < | | | | | | > < < | < > > > | < > < < < < | < < < | | | | > > > > | | | | | > > > > > > > > | > > | > > > | | | > > > > > > > > > > | > | > > > > > | > > > | > | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
**
*******************************************************************************
**
** This file contains code that implements the client-side HTTP protocol
*/
#include "config.h"
#include "http.h"
#include <assert.h>
/*
** Construct the "login" card with the client credentials.
**
** login LOGIN NONCE SIGNATURE
**
** The LOGIN is the user id of the client. NONCE is the sha1 checksum
** of all payload that follows the login card. SIGNATURE is the sha1
** checksum of the nonce followed by the user password.
**
** Write the constructed login card into pLogin. pLogin is initialized
** by this routine.
*/
static void http_build_login_card(Blob *pPayload, Blob *pLogin){
Blob nonce; /* The nonce */
Blob pw; /* The user password */
Blob sig; /* The signature field */
blob_zero(&nonce);
blob_zero(&pw);
sha1sum_blob(pPayload, &nonce);
blob_copy(&pw, &nonce);
blob_zero(pLogin);
if( g.urlUser==0 ){
user_select();
db_blob(&pw, "SELECT pw FROM user WHERE uid=%d", g.userUid);
sha1sum_blob(&pw, &sig);
blob_appendf(pLogin, "login %s %b %b\n", g.zLogin, &nonce, &sig);
}else{
if( g.urlPasswd==0 ){
if( strcmp(g.urlUser,"anonymous")!=0 ){
char *zPrompt = mprintf("password for %s: ", g.urlUser);
Blob x;
prompt_for_password(zPrompt, &x, 0);
free(zPrompt);
g.urlPasswd = blob_str(&x);
}else{
g.urlPasswd = "";
}
}
blob_append(&pw, g.urlPasswd, -1);
sha1sum_blob(&pw, &sig);
blob_appendf(pLogin, "login %s %b %b\n", g.urlUser, &nonce, &sig);
}
blob_reset(&nonce);
blob_reset(&pw);
blob_reset(&sig);
}
/*
** Construct an appropriate HTTP request header. Write the header
** into pHdr. This routine initializes the pHdr blob. pPayload is
** the complete payload (including the login card) already compressed.
*/
static void http_build_header(Blob *pPayload, Blob *pHdr){
int i;
const char *zSep;
blob_zero(pHdr);
i = strlen(g.urlPath);
if( i>0 && g.urlPath[i-1]=='/' ){
zSep = "";
}else{
zSep = "/";
}
blob_appendf(pHdr, "POST %s%sxfer HTTP/1.1\r\n", g.urlPath, zSep);
blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
blob_appendf(pHdr, "User-Agent: Fossil/" MANIFEST_VERSION "\r\n");
if( g.fHttpTrace ){
blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
}else{
blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
}
blob_appendf(pHdr, "Content-Length: %d\r\n\r\n", blob_size(pPayload));
}
/*
** Sign the content in pSend, compress it, and send it to the server
** via HTTP or HTTPS. Get a reply, uncompress the reply, and store the reply
** in pRecv. pRecv is assumed to be uninitialized when
** this routine is called - this routine will initialize it.
**
** The server address is contain in the "g" global structure. The
** url_parse() routine should have been called prior to this routine
** in order to fill this structure appropriately.
*/
void http_exchange(Blob *pSend, Blob *pReply){
Blob login; /* The login card */
Blob payload; /* The complete payload including login card */
Blob hdr; /* The HTTP request header */
int closeConnection; /* True to close the connection when done */
int iLength; /* Length of the reply payload */
int rc; /* Result code */
int iHttpVersion; /* Which version of HTTP protocol server uses */
char *zLine; /* A single line of the reply header */
int i; /* Loop counter */
if( transport_open() ){
fossil_fatal(transport_errmsg());
}
/* Construct the login card and prepare the complete payload */
http_build_login_card(pSend, &login);
if( g.fHttpTrace ){
payload = login;
blob_append(&payload, blob_buffer(pSend), blob_size(pSend));
}else{
blob_compress2(&login, pSend, &payload);
blob_reset(&login);
}
/* Construct the HTTP request header */
http_build_header(&payload, &hdr);
/* When tracing, write the transmitted HTTP message both to standard
** output and into a file. The file can then be used to drive the
** server-side like this:
**
** ./fossil http <http-trace-1.txt
*/
if( g.fHttpTrace ){
static int traceCnt = 0;
char *zOutFile;
FILE *out;
traceCnt++;
zOutFile = mprintf("http-trace-%d.txt", traceCnt);
printf("HTTP SEND: (%s)\n%s%s=======================\n",
zOutFile, blob_str(&hdr), blob_str(&payload));
out = fopen(zOutFile, "w");
if( out ){
fwrite(blob_buffer(&hdr), 1, blob_size(&hdr), out);
fwrite(blob_buffer(&payload), 1, blob_size(&payload), out);
fclose(out);
}
}
/*
** Send the request to the server.
*/
transport_send(&hdr);
transport_send(&payload);
blob_reset(&hdr);
blob_reset(&payload);
/*
** Read and interpret the server reply
*/
closeConnection = 1;
iLength = -1;
while( (zLine = transport_receive_line())!=0 && zLine[0]!=0 ){
if( strncasecmp(zLine, "http/1.", 7)==0 ){
if( sscanf(zLine, "HTTP/1.%d %d", &iHttpVersion, &rc)!=2 ) goto write_err;
if( rc!=200 ) goto write_err;
if( iHttpVersion==0 ){
closeConnection = 1;
}else{
closeConnection = 0;
}
} else if( strncasecmp(zLine, "content-length:", 15)==0 ){
for(i=15; isspace(zLine[i]); i++){}
iLength = atoi(&zLine[i]);
}else if( strncasecmp(zLine, "connection:", 11)==0 ){
char c;
for(i=11; isspace(zLine[i]); i++){}
c = zLine[i];
if( c=='c' || c=='C' ){
closeConnection = 1;
}else if( c=='k' || c=='K' ){
closeConnection = 0;
}
}
}
/*
** Extract the reply payload that follows the header
*/
if( iLength<0 ) goto write_err;
blob_zero(pReply);
blob_resize(pReply, iLength);
iLength = transport_receive(blob_buffer(pReply), iLength);
blob_resize(pReply, iLength);
if( g.fHttpTrace ){
printf("HTTP RECEIVE:\n%s\n=======================\n", blob_str(pReply));
}else{
blob_uncompress(pReply, pReply);
}
/*
** Close the connection to the server if appropriate.
*/
if( closeConnection ){
transport_close();
}
return;
/*
** Jump to here if an error is seen.
*/
write_err:
transport_close();
return;
}
|
Added src/http_socket.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
/*
** Copyright (c) 2009 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public
** License version 2 as published by the Free Software Foundation.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** General Public License for more details.
**
** You should have received a copy of the GNU General Public
** License along with this library; if not, write to the
** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
** Boston, MA 02111-1307, USA.
**
** Author contact information:
** drh@hwaci.com
** http://www.hwaci.com/drh/
**
*******************************************************************************
**
** This file manages low-level client socket communications. The socket
** might be for a simple HTTP request or for an encrypted HTTPS request.
**
** This file implements a singleton. A single client socket may be active
** at a time. State information is stored in static variables. The identity
** of the server is held in global variables that are set by url_parse().
**
** Low-level sockets are abstracted out into this module because they
** are handled different on Unix and windows.
*/
#include "config.h"
#include "http_socket.h"
#ifdef __MINGW32__
# include <windows.h>
# include <winsock2.h>
#else
# include <arpa/inet.h>
# include <sys/socket.h>
# include <netdb.h>
# include <netinet/in.h>
#endif
#include <assert.h>
#include <sys/types.h>
#include <signal.h>
/*
** There can only be a single socket connection open at a time.
** State information about that socket is stored in the following
** local variables:
*/
static int socketIsInit = 0; /* True after global initialization */
#ifdef __MINGW32__
static WSADATA socketInfo; /* Windows socket initialize data */
#endif
static int iSocket = -1; /* The socket on which we talk to the server */
static char *socketErrMsg = 0; /* Text of most recent socket error */
/*
** Clear the socket error message
*/
static void socket_clear_errmsg(void){
free(socketErrMsg);
socketErrMsg = 0;
}
/*
** Set the socket error message.
*/
void socket_set_errmsg(char *zFormat, ...){
va_list ap;
socket_clear_errmsg();
va_start(ap, zFormat);
socketErrMsg = vmprintf(zFormat, ap);
va_end(ap);
}
/*
** Return the current socket error message
*/
const char *socket_errmsg(void){
return socketErrMsg;
}
/*
** Call this routine once before any other use of the socket interface.
** This routine does initial configuration of the socket module.
*/
void socket_global_init(void){
if( socketIsInit==0 ){
#ifdef __MINGW32__
if( WSAStartup(MAKEWORD(2,0), &socketInfo)!=0 ){
fossil_panic("can't initialize winsock");
}
#endif
socketIsInit = 1;
}
}
/*
** Call this routine to shutdown the socket module prior to program
** exit.
*/
void socket_global_shutdown(void){
if( socketIsInit ){
#ifdef __MINGW32__
WSACleanup();
#endif
socket_clear_errmsg();
socketIsInit = 0;
}
}
/*
** Close the currently open socket. If no socket is open, this routine
** is a no-op.
*/
void socket_close(void){
if( iSocket>=0 ){
#ifdef __MINGW32__
closesocket(iSocket);
#else
close(iSocket);
#endif
iSocket = -1;
}
}
/*
** Open a socket connection. The identify of the server is determined
** by global varibles that are set using url_parse():
**
** g.urlName Name of the server. Ex: www.fossil-scm.org
** g.urlPort TCP/IP port to use. Ex: 80
**
** Return the number of errors.
*/
int socket_open(void){
static struct sockaddr_in addr; /* The server address */
static int addrIsInit = 0; /* True once addr is initialized */
socket_global_init();
if( !addrIsInit ){
addr.sin_family = AF_INET;
addr.sin_port = htons(g.urlPort);
*(int*)&addr.sin_addr = inet_addr(g.urlName);
if( -1 == *(int*)&addr.sin_addr ){
#ifndef FOSSIL_STATIC_LINK
struct hostent *pHost;
pHost = gethostbyname(g.urlName);
if( pHost!=0 ){
memcpy(&addr.sin_addr,pHost->h_addr_list[0],pHost->h_length);
}else
#endif
{
socket_set_errmsg("can't resolve host name: %s\n", g.urlName);
return 1;
}
}
addrIsInit = 1;
/* Set the Global.zIpAddr variable to the server we are talking to.
** This is used to populate the ipaddr column of the rcvfrom table,
** if any files are received from the server.
*/
g.zIpAddr = mprintf("%s", inet_ntoa(addr.sin_addr));
}
iSocket = socket(AF_INET,SOCK_STREAM,0);
if( iSocket<0 ){
socket_set_errmsg("cannot create a socket");
return 1;
}
if( connect(iSocket,(struct sockaddr*)&addr,sizeof(addr))<0 ){
socket_set_errmsg("cannot connect to host %s:%d", g.urlName, g.urlPort);
socket_close();
return 1;
}
#ifndef __MINGW32__
signal(SIGPIPE, SIG_IGN);
#endif
return 0;
}
/*
** Send content out over the open socket connection.
*/
size_t socket_send(void *NotUsed, void *pContent, size_t N){
size_t sent;
size_t total = 0;
while( N>0 ){
sent = send(iSocket, pContent, N, 0);
if( sent<=0 ) break;
total += sent;
N -= sent;
pContent = (void*)&((char*)pContent)[sent];
}
return total;
}
/*
** Receive content back from the open socket connection.
*/
size_t socket_receive(void *NotUsed, void *pContent, size_t N){
size_t got;
size_t total = 0;
while( N>0 ){
got = recv(iSocket, pContent, N, 0);
if( got<=0 ) break;
total += got;
N -= got;
pContent = (void*)&((char*)pContent)[got];
}
return total;
}
|
Added src/http_transport.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
/*
** Copyright (c) 2009 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public
** License version 2 as published by the Free Software Foundation.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** General Public License for more details.
**
** You should have received a copy of the GNU General Public
** License along with this library; if not, write to the
** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
** Boston, MA 02111-1307, USA.
**
** Author contact information:
** drh@hwaci.com
** http://www.hwaci.com/drh/
**
*******************************************************************************
**
** This module implements the transport layer for the client side HTTP
** connection. The purpose of this layer is to provide a common interface
** for both HTTP and HTTPS and to provide a common "fetch one line"
** interface that is used for parsing the reply.
*/
#include "config.h"
#include "http_transport.h"
/*
** State information
*/
static struct {
int isOpen; /* True when the transport layer is open */
char *pBuf; /* Buffer used to hold the reply */
int nAlloc; /* Space allocated for transportBuf[] */
int nUsed ; /* Space of transportBuf[] used */
int iCursor; /* Next unread by in transportBuf[] */
} transport = {
0, 0, 0, 0
};
/*
** Return the current transport error message.
*/
const char *transport_errmsg(void){
return socket_errmsg();
}
/*
** Open a connection to the server. The server is defined by the following
** global variables:
**
** g.urlName Name of the server. Ex: www.fossil-scm.org
** g.urlPort TCP/IP port. Ex: 80
** g.urlIsHttps Use TLS for the connection
**
** Return the number of errors.
*/
int transport_open(void){
int rc = 0;
if( g.urlIsHttps ){
socket_set_errmsg("TLS is not yet implemented");
rc = 1;
}else{
rc = socket_open();
if( rc==0 ) transport.isOpen = 1;
}
return rc;
}
/*
** Close the current connection
*/
void transport_close(void){
if( transport.isOpen ){
socket_close();
free(transport.pBuf);
transport.pBuf = 0;
transport.nAlloc = 0;
transport.nUsed = 0;
transport.iCursor = 0;
}
}
/*
** Send content over the wire.
*/
void transport_send(Blob *toSend){
char *z = blob_buffer(toSend);
int n = blob_size(toSend);
int sent;
while( n>0 ){
sent = socket_send(0, z, n);
if( sent<=0 ) break;
n -= sent;
}
}
/*
** Read N bytes of content from the wire and store in the supplied buffer.
** Return the number of bytes actually received.
*/
int transport_receive(char *zBuf, int N){
int onHand; /* Bytes current held in the transport buffer */
int nByte = 0; /* Bytes of content received */
onHand = transport.nUsed - transport.iCursor;
if( onHand>0 ){
int toMove = onHand;
if( toMove>N ) toMove = N;
memcpy(zBuf, &transport.pBuf[transport.iCursor], toMove);
transport.iCursor += toMove;
if( transport.iCursor>=transport.nUsed ){
transport.nUsed = 0;
transport.iCursor = 0;
}
N -= toMove;
zBuf += toMove;
nByte += toMove;
}
if( N>0 ){
int got = socket_receive(0, zBuf, N);
if( got>0 ){
nByte += got;
}
}
return nByte;
}
/*
** Load up to N new bytes of content into the transport.pBuf buffer.
** The buffer itself might be moved. And the transport.iCursor value
** might be reset to 0.
*/
static void transport_load_buffer(int N){
int i, j;
if( transport.nAlloc==0 ){
transport.nAlloc = N;
transport.pBuf = malloc( N );
if( transport.pBuf==0 ) fossil_panic("out of memory");
transport.iCursor = 0;
transport.nUsed = 0;
}
if( transport.iCursor>0 ){
for(i=0, j=transport.iCursor; j<transport.nUsed; i++, j++){
transport.pBuf[i] = transport.pBuf[j];
}
transport.nUsed -= transport.iCursor;
transport.iCursor = 0;
}
if( transport.nUsed + N > transport.nAlloc ){
char *pNew;
transport.nAlloc = transport.nUsed + N;
pNew = realloc(transport.pBuf, transport.nAlloc);
if( pNew==0 ) fossil_panic("out of memory");
transport.pBuf = pNew;
}
if( N>0 ){
i = transport_receive(&transport.pBuf[transport.nUsed], N);
if( i>0 ){
transport.nUsed += i;
}
}
}
/*
** Fetch a single line of input where a line is all text up to the next
** \n character or until the end of input. Remove all trailing whitespace
** from the received line and zero-terminate the result. Return a pointer
** to the line.
**
** Each call to this routine potentially overwrites the returned buffer.
*/
char *transport_receive_line(void){
int i;
int iStart;
i = iStart = transport.iCursor;
while(1){
if( i >= transport.nUsed ){
transport_load_buffer(1000);
i -= iStart;
iStart = 0;
if( i >= transport.nUsed ){
transport.pBuf[i] = 0;
transport.iCursor = i;
break;
}
}
if( transport.pBuf[i]=='\n' ){
transport.iCursor = i+1;
while( i>=iStart && isspace(transport.pBuf[i]) ){
transport.pBuf[i] = 0;
i--;
}
break;
}
i++;
}
return &transport.pBuf[iStart];
}
|
Changes to src/main.mk.
| ︙ | ︙ | |||
35 36 37 38 39 40 41 42 43 44 45 46 47 48 | $(SRCDIR)/descendants.c \ $(SRCDIR)/diff.c \ $(SRCDIR)/diffcmd.c \ $(SRCDIR)/doc.c \ $(SRCDIR)/encode.c \ $(SRCDIR)/file.c \ $(SRCDIR)/http.c \ $(SRCDIR)/info.c \ $(SRCDIR)/login.c \ $(SRCDIR)/main.c \ $(SRCDIR)/manifest.c \ $(SRCDIR)/md5.c \ $(SRCDIR)/merge.c \ $(SRCDIR)/merge3.c \ | > > | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | $(SRCDIR)/descendants.c \ $(SRCDIR)/diff.c \ $(SRCDIR)/diffcmd.c \ $(SRCDIR)/doc.c \ $(SRCDIR)/encode.c \ $(SRCDIR)/file.c \ $(SRCDIR)/http.c \ $(SRCDIR)/http_socket.c \ $(SRCDIR)/http_transport.c \ $(SRCDIR)/info.c \ $(SRCDIR)/login.c \ $(SRCDIR)/main.c \ $(SRCDIR)/manifest.c \ $(SRCDIR)/md5.c \ $(SRCDIR)/merge.c \ $(SRCDIR)/merge3.c \ |
| ︙ | ︙ | |||
103 104 105 106 107 108 109 110 111 112 113 114 115 116 | descendants_.c \ diff_.c \ diffcmd_.c \ doc_.c \ encode_.c \ file_.c \ http_.c \ info_.c \ login_.c \ main_.c \ manifest_.c \ md5_.c \ merge_.c \ merge3_.c \ | > > | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | descendants_.c \ diff_.c \ diffcmd_.c \ doc_.c \ encode_.c \ file_.c \ http_.c \ http_socket_.c \ http_transport_.c \ info_.c \ login_.c \ main_.c \ manifest_.c \ md5_.c \ merge_.c \ merge3_.c \ |
| ︙ | ︙ | |||
171 172 173 174 175 176 177 178 179 180 181 182 183 184 | descendants.o \ diff.o \ diffcmd.o \ doc.o \ encode.o \ file.o \ http.o \ info.o \ login.o \ main.o \ manifest.o \ md5.o \ merge.o \ merge3.o \ | > > | 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | descendants.o \ diff.o \ diffcmd.o \ doc.o \ encode.o \ file.o \ http.o \ http_socket.o \ http_transport.o \ info.o \ login.o \ main.o \ manifest.o \ md5.o \ merge.o \ merge3.o \ |
| ︙ | ︙ | |||
253 254 255 256 257 258 259 | # $(SRCDIR)/../manifest: # noop clean: rm -f *.o *_.c $(APPNAME) VERSION.h rm -f translate makeheaders mkindex page_index.h headers | | | | 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 | # $(SRCDIR)/../manifest: # noop clean: rm -f *.o *_.c $(APPNAME) VERSION.h rm -f translate makeheaders mkindex page_index.h headers rm -f add.h admin.h allrepo.h bag.h blob.h branch.h browse.h cgi.h checkin.h checkout.h clearsign.h clone.h comformat.h configure.h construct.h content.h db.h delta.h deltacmd.h descendants.h diff.h diffcmd.h doc.h encode.h file.h http.h http_socket.h http_transport.h info.h login.h main.h manifest.h md5.h merge.h merge3.h my_page.h name.h pivot.h pqueue.h printf.h rebuild.h report.h rss.h rstats.h schema.h setup.h sha1.h shun.h stat.h style.h sync.h tag.h tagview.h th_main.h timeline.h tkt.h tktsetup.h undo.h update.h url.h user.h verify.h vfile.h wiki.h wikiformat.h winhttp.h xfer.h zip.h page_index.h: $(TRANS_SRC) mkindex ./mkindex $(TRANS_SRC) >$@ headers: page_index.h makeheaders VERSION.h ./makeheaders add_.c:add.h admin_.c:admin.h allrepo_.c:allrepo.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h construct_.c:construct.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h file_.c:file.h http_.c:http.h http_socket_.c:http_socket.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h my_page_.c:my_page.h name_.c:name.h pivot_.c:pivot.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h rstats_.c:rstats.h schema_.c:schema.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tagview_.c:tagview.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h VERSION.h touch headers headers: Makefile Makefile: add_.c: $(SRCDIR)/add.c $(SRCDIR)/VERSION translate ./translate $(SRCDIR)/add.c | sed -f $(SRCDIR)/VERSION >add_.c add.o: add_.c add.h $(SRCDIR)/config.h |
| ︙ | ︙ | |||
444 445 446 447 448 449 450 451 452 453 454 455 456 457 | http_.c: $(SRCDIR)/http.c $(SRCDIR)/VERSION translate ./translate $(SRCDIR)/http.c | sed -f $(SRCDIR)/VERSION >http_.c http.o: http_.c http.h $(SRCDIR)/config.h $(XTCC) -o http.o -c http_.c http.h: headers info_.c: $(SRCDIR)/info.c $(SRCDIR)/VERSION translate ./translate $(SRCDIR)/info.c | sed -f $(SRCDIR)/VERSION >info_.c info.o: info_.c info.h $(SRCDIR)/config.h $(XTCC) -o info.o -c info_.c info.h: headers | > > > > > > > > > > > > > > | 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 | http_.c: $(SRCDIR)/http.c $(SRCDIR)/VERSION translate ./translate $(SRCDIR)/http.c | sed -f $(SRCDIR)/VERSION >http_.c http.o: http_.c http.h $(SRCDIR)/config.h $(XTCC) -o http.o -c http_.c http.h: headers http_socket_.c: $(SRCDIR)/http_socket.c $(SRCDIR)/VERSION translate ./translate $(SRCDIR)/http_socket.c | sed -f $(SRCDIR)/VERSION >http_socket_.c http_socket.o: http_socket_.c http_socket.h $(SRCDIR)/config.h $(XTCC) -o http_socket.o -c http_socket_.c http_socket.h: headers http_transport_.c: $(SRCDIR)/http_transport.c $(SRCDIR)/VERSION translate ./translate $(SRCDIR)/http_transport.c | sed -f $(SRCDIR)/VERSION >http_transport_.c http_transport.o: http_transport_.c http_transport.h $(SRCDIR)/config.h $(XTCC) -o http_transport.o -c http_transport_.c http_transport.h: headers info_.c: $(SRCDIR)/info.c $(SRCDIR)/VERSION translate ./translate $(SRCDIR)/info.c | sed -f $(SRCDIR)/VERSION >info_.c info.o: info_.c info.h $(SRCDIR)/config.h $(XTCC) -o info.o -c info_.c info.h: headers |
| ︙ | ︙ |
Changes to src/makemake.tcl.
| ︙ | ︙ | |||
29 30 31 32 33 34 35 36 37 38 39 40 41 42 | descendants diff diffcmd doc encode file http info login main manifest md5 merge merge3 | > > | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | descendants diff diffcmd doc encode file http http_socket http_transport info login main manifest md5 merge merge3 |
| ︙ | ︙ | |||
193 194 195 196 197 198 199 | puts "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o sqlite3.o\n" puts "th.o:\t\$(SRCDIR)/th.c" puts "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th.c -o th.o\n" puts "th_lang.o:\t\$(SRCDIR)/th_lang.c" puts "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th_lang.c -o th_lang.o\n" | < | 195 196 197 198 199 200 201 | puts "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o sqlite3.o\n" puts "th.o:\t\$(SRCDIR)/th.c" puts "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th.c -o th.o\n" puts "th_lang.o:\t\$(SRCDIR)/th_lang.c" puts "\t\$(XTCC) -I\$(SRCDIR) -c \$(SRCDIR)/th_lang.c -o th_lang.o\n" |
Changes to src/xfer.c.
| ︙ | ︙ | |||
846 847 848 849 850 851 852 | ** routine is called by the client. ** ** Records are pushed to the server if pushFlag is true. Records ** are pulled if pullFlag is true. A full sync occurs if both are ** true. */ void client_sync( | | | | | | | < < | | | | | > > > | 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 |
** routine is called by the client.
**
** Records are pushed to the server if pushFlag is true. Records
** are pulled if pullFlag is true. A full sync occurs if both are
** true.
*/
void client_sync(
int pushFlag, /* True to do a push (or a sync) */
int pullFlag, /* True to do a pull (or a sync) */
int cloneFlag, /* True if this is a clone */
int configRcvMask, /* Receive these configuration items */
int configSendMask /* Send these configuration items */
){
int go = 1; /* Loop until zero */
int nCard = 0; /* Number of cards sent or received */
int nCycle = 0; /* Number of round trips to the server */
int size; /* Size of a config value */
int nFileSend = 0;
int origConfigRcvMask; /* Original value of configRcvMask */
int nFileRecv; /* Number of files received */
int mxPhantomReq = 200; /* Max number of phantoms to request per comm */
const char *zCookie; /* Server cookie */
Blob send; /* Text we are sending to the server */
Blob recv; /* Reply we got back from the server */
Xfer xfer; /* Transfer data */
const char *zSCode = db_get("server-code", "x");
const char *zPCode = db_get("project-code", 0);
socket_global_init();
memset(&xfer, 0, sizeof(xfer));
xfer.pIn = &recv;
xfer.pOut = &send;
xfer.mxSend = db_get_int("max-upload", 250000);
assert( pushFlag | pullFlag | cloneFlag | configRcvMask | configSendMask );
assert( !g.urlIsFile ); /* This only works for networking */
|
| ︙ | ︙ | |||
1174 1175 1176 1177 1178 1179 1180 |
/* If we have one or more files queued to send, then go
** another round
*/
if( xfer.nFileSent+xfer.nDeltaSent>0 ){
go = 1;
}
};
| | > | 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 |
/* If we have one or more files queued to send, then go
** another round
*/
if( xfer.nFileSent+xfer.nDeltaSent>0 ){
go = 1;
}
};
transport_close();
socket_global_shutdown();
db_multi_exec("DROP TABLE onremote");
db_end_transaction(0);
}
|