Fossil

Diff
Login

Differences From Artifact [6ddf67d9b3]:

To Artifact [e7abc65c4b]:


18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32







-
+







** 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 
** 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"
#if defined(_WIN32)
#  include <winsock2.h>
61
62
63
64
65
66
67
68

69
70
71
72
73
74
75
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75







-
+







  free(socketErrMsg);
  socketErrMsg = 0;
}

/*
** Set the socket error message.
*/
void socket_set_errmsg(char *zFormat, ...){
void socket_set_errmsg(const char *zFormat, ...){
  va_list ap;
  socket_clear_errmsg();
  va_start(ap, zFormat);
  socketErrMsg = vmprintf(zFormat, ap);
  va_end(ap);
}

122
123
124
125
126
127
128
129

130
131
132


133
134
135
136
137
138
139
122
123
124
125
126
127
128

129
130


131
132
133
134
135
136
137
138
139







-
+

-
-
+
+







#endif
    iSocket = -1;
  }
}

/*
** Open a socket connection.  The identify of the server is determined
** by global variables that are set using url_parse():
** by pUrlData
**
**    g.urlName       Name of the server.  Ex: www.fossil-scm.org
**    g.urlPort       TCP/IP port to use.  Ex: 80
**    pUrlDAta->name       Name of the server.  Ex: www.fossil-scm.org
**    pUrlDAta->port       TCP/IP port to use.  Ex: 80
**
** Return the number of errors.
*/
int socket_open(UrlData *pUrlData){
  int error = 0;
#ifdef HAVE_GETADDRINFO
  struct addrinfo hints;
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
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







-
+

-
-
+
+



















-
+







  hints.ai_family = PF_UNSPEC;
#else
  hints.ai_family = PF_INET;
#endif
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_protocol = IPPROTO_TCP;

  sPort = mprintf("%d", g.urlPort);
  sPort = mprintf("%d", pUrlData->port);

  if(getaddrinfo(g.urlName, sPort, &hints, &res)) {
    socket_set_errmsg("can't resolve host name: %s", g.urlName);
  if(getaddrinfo(pUrlData->name, sPort, &hints, &res)) {
    socket_set_errmsg("can't resolve host name: %s", pUrlData->name);
    free(sPort);
    return 1;
  }
  for(i = res; i; i = i->ai_next) {
    iSocket = socket(i->ai_family, i->ai_socktype, i->ai_protocol);
    if(iSocket < 0) {
      continue;
    }
    if(connect(iSocket, i->ai_addr, i->ai_addrlen) < 0) {
      close(iSocket);
      iSocket = -1;
      continue;
    }
    if(!getnameinfo(i->ai_addr, i->ai_addrlen, ip, sizeof(ip),
                    NULL, 0, NI_NUMERICHOST))
        g.zIpAddr = mprintf("%s", ip);
    break;
  }
  if(iSocket == -1) {
    socket_set_errmsg("cannot connect to host %s:%s", g.urlName, sPort);
    socket_set_errmsg("cannot connect to host %s:%s", pUrlData->name, sPort);
    error = 1;
  }
  free(sPort);
  freeaddrinfo(res);
#else
  static struct sockaddr_in addr;  /* The server address */
  static int addrIsInit = 0;       /* True once addr is initialized */
260
261
262
263
264
265
266
267
268
269




270
271
272
273
274
275
276
277
278
279
280
281
260
261
262
263
264
265
266



267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282







-
-
-
+
+
+
+












    N -= (size_t)got;
    pContent = (void*)&((char*)pContent)[got];
  }
  return total;
}

/*
** Attempt to resolve g.urlName to IP and setup g.zIpAddr so rcvfrom gets
** populated. For hostnames with more than one IP (or if overridden in
** ~/.ssh/config) the rcvfrom may not match the host to which we connect.
** Attempt to resolve pUrlData->name to an IP address and setup g.zIpAddr
** so rcvfrom gets populated. For hostnames with more than one IP (or
** if overridden in ~/.ssh/config) the rcvfrom may not match the host
** to which we connect.
*/
void socket_ssh_resolve_addr(UrlData *pUrlData){
  struct hostent *pHost;        /* Used to make best effort for rcvfrom */
  struct sockaddr_in addr;

  memset(&addr, 0, sizeof(addr));
  pHost = gethostbyname(pUrlData->name);
  if( pHost!=0 ){
    memcpy(&addr.sin_addr,pHost->h_addr_list[0],pHost->h_length);
    g.zIpAddr = mprintf("%s", inet_ntoa(addr.sin_addr));
  }
}