-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathurldata.h
1949 lines (1759 loc) · 77.3 KB
/
urldata.h
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
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
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
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
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
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#ifndef HEADER_CURL_URLDATA_H
#define HEADER_CURL_URLDATA_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <[email protected]>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/* This file is for lib internal stuff */
#include "curl_setup.h"
#define PORT_FTP 21
#define PORT_FTPS 990
#define PORT_TELNET 23
#define PORT_HTTP 80
#define PORT_HTTPS 443
#define PORT_DICT 2628
#define PORT_LDAP 389
#define PORT_LDAPS 636
#define PORT_TFTP 69
#define PORT_SSH 22
#define PORT_IMAP 143
#define PORT_IMAPS 993
#define PORT_POP3 110
#define PORT_POP3S 995
#define PORT_SMB 445
#define PORT_SMBS 445
#define PORT_SMTP 25
#define PORT_SMTPS 465 /* sometimes called SSMTP */
#define PORT_RTSP 554
#define PORT_RTMP 1935
#define PORT_RTMPT PORT_HTTP
#define PORT_RTMPS PORT_HTTPS
#define PORT_GOPHER 70
#define PORT_MQTT 1883
#ifdef USE_WEBSOCKETS
/* CURLPROTO_GOPHERS (29) is the highest publicly used protocol bit number,
* the rest are internal information. If we use higher bits we only do this on
* platforms that have a >= 64 bit type and then we use such a type for the
* protocol fields in the protocol handler.
*/
#define CURLPROTO_WS (1<<30)
#define CURLPROTO_WSS ((curl_prot_t)1<<31)
#else
#define CURLPROTO_WS 0
#define CURLPROTO_WSS 0
#endif
/* This should be undefined once we need bit 32 or higher */
#define PROTO_TYPE_SMALL
#ifndef PROTO_TYPE_SMALL
typedef curl_off_t curl_prot_t;
#else
typedef unsigned int curl_prot_t;
#endif
/* This mask is for all the old protocols that are provided and defined in the
public header and shall exclude protocols added since which are not exposed
in the API */
#define CURLPROTO_MASK (0x3ffffff)
#define DICT_MATCH "/MATCH:"
#define DICT_MATCH2 "/M:"
#define DICT_MATCH3 "/FIND:"
#define DICT_DEFINE "/DEFINE:"
#define DICT_DEFINE2 "/D:"
#define DICT_DEFINE3 "/LOOKUP:"
#define CURL_DEFAULT_USER "anonymous"
#define CURL_DEFAULT_PASSWORD "[email protected]"
/* Convenience defines for checking protocols or their SSL based version. Each
protocol handler should only ever have a single CURLPROTO_ in its protocol
field. */
#define PROTO_FAMILY_HTTP (CURLPROTO_HTTP|CURLPROTO_HTTPS|CURLPROTO_WS| \
CURLPROTO_WSS)
#define PROTO_FAMILY_FTP (CURLPROTO_FTP|CURLPROTO_FTPS)
#define PROTO_FAMILY_POP3 (CURLPROTO_POP3|CURLPROTO_POP3S)
#define PROTO_FAMILY_SMB (CURLPROTO_SMB|CURLPROTO_SMBS)
#define PROTO_FAMILY_SMTP (CURLPROTO_SMTP|CURLPROTO_SMTPS)
#define PROTO_FAMILY_SSH (CURLPROTO_SCP|CURLPROTO_SFTP)
#define DEFAULT_CONNCACHE_SIZE 5
/* length of longest IPv6 address string including the trailing null */
#define MAX_IPADR_LEN sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")
/* Default FTP/IMAP etc response timeout in milliseconds */
#define RESP_TIMEOUT (120*1000)
/* Max string input length is a precaution against abuse and to detect junk
input easier and better. */
#define CURL_MAX_INPUT_LENGTH 8000000
#include "cookie.h"
#include "psl.h"
#include "formdata.h"
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_NETINET_IN6_H
#include <netinet/in6.h>
#endif
#include "timeval.h"
#include <curl/curl.h>
#include "http_chunks.h" /* for the structs and enum stuff */
#include "hostip.h"
#include "hash.h"
#include "splay.h"
#include "dynbuf.h"
/* return the count of bytes sent, or -1 on error */
typedef ssize_t (Curl_send)(struct Curl_easy *data, /* transfer */
int sockindex, /* socketindex */
const void *buf, /* data to write */
size_t len, /* max amount to write */
CURLcode *err); /* error to return */
/* return the count of bytes read, or -1 on error */
typedef ssize_t (Curl_recv)(struct Curl_easy *data, /* transfer */
int sockindex, /* socketindex */
char *buf, /* store data here */
size_t len, /* max amount to read */
CURLcode *err); /* error to return */
#ifdef USE_HYPER
typedef CURLcode (*Curl_datastream)(struct Curl_easy *data,
struct connectdata *conn,
int *didwhat,
bool *done,
int select_res);
#endif
#include "mime.h"
#include "imap.h"
#include "pop3.h"
#include "smtp.h"
#include "ftp.h"
#include "file.h"
#include "vssh/ssh.h"
#include "http.h"
#include "rtsp.h"
#include "smb.h"
#include "mqtt.h"
#include "wildcard.h"
#include "multihandle.h"
#include "c-hyper.h"
#include "cf-socket.h"
#ifdef HAVE_GSSAPI
# ifdef HAVE_GSSGNU
# include <gss.h>
# elif defined HAVE_GSSAPI_GSSAPI_H
# include <gssapi/gssapi.h>
# else
# include <gssapi.h>
# endif
# ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
# include <gssapi/gssapi_generic.h>
# endif
#endif
#ifdef USE_LIBSSH2
#include <libssh2.h>
#include <libssh2_sftp.h>
#endif /* USE_LIBSSH2 */
#define READBUFFER_SIZE CURL_MAX_WRITE_SIZE
#define READBUFFER_MAX CURL_MAX_READ_SIZE
#define READBUFFER_MIN 1024
/* The default upload buffer size, should not be smaller than
CURL_MAX_WRITE_SIZE, as it needs to hold a full buffer as could be sent in
a write callback.
The size was 16KB for many years but was bumped to 64KB because it makes
libcurl able to do significantly faster uploads in some circumstances. Even
larger buffers can help further, but this is deemed a fair memory/speed
compromise. */
#define UPLOADBUFFER_DEFAULT 65536
#define UPLOADBUFFER_MAX (2*1024*1024)
#define UPLOADBUFFER_MIN CURL_MAX_WRITE_SIZE
#define CURLEASY_MAGIC_NUMBER 0xc0dedbadU
#define GOOD_EASY_HANDLE(x) \
((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER))
#ifdef HAVE_GSSAPI
/* Types needed for krb5-ftp connections */
struct krb5buffer {
void *data;
size_t size;
size_t index;
BIT(eof_flag);
};
enum protection_level {
PROT_NONE, /* first in list */
PROT_CLEAR,
PROT_SAFE,
PROT_CONFIDENTIAL,
PROT_PRIVATE,
PROT_CMD,
PROT_LAST /* last in list */
};
#endif
/* enum for the nonblocking SSL connection state machine */
typedef enum {
ssl_connect_1,
ssl_connect_2,
ssl_connect_2_reading,
ssl_connect_2_writing,
ssl_connect_3,
ssl_connect_done
} ssl_connect_state;
typedef enum {
ssl_connection_none,
ssl_connection_negotiating,
ssl_connection_complete
} ssl_connection_state;
/* SSL backend-specific data; declared differently by each SSL backend */
struct ssl_backend_data;
struct ssl_primary_config {
char *CApath; /* certificate dir (doesn't work on windows) */
char *CAfile; /* certificate to verify peer against */
char *issuercert; /* optional issuer certificate filename */
char *clientcert;
char *cipher_list; /* list of ciphers to use */
char *cipher_list13; /* list of TLS 1.3 cipher suites to use */
char *pinned_key;
char *CRLfile; /* CRL to check certificate revocation */
struct curl_blob *cert_blob;
struct curl_blob *ca_info_blob;
struct curl_blob *issuercert_blob;
#ifdef USE_TLS_SRP
char *username; /* TLS username (for, e.g., SRP) */
char *password; /* TLS password (for, e.g., SRP) */
#endif
char *curves; /* list of curves to use */
unsigned char ssl_options; /* the CURLOPT_SSL_OPTIONS bitmask */
unsigned int version_max; /* max supported version the client wants to use */
unsigned char version; /* what version the client wants to use */
BIT(verifypeer); /* set TRUE if this is desired */
BIT(verifyhost); /* set TRUE if CN/SAN must match hostname */
BIT(verifystatus); /* set TRUE if certificate status must be checked */
BIT(sessionid); /* cache session IDs or not */
};
struct ssl_config_data {
struct ssl_primary_config primary;
long certverifyresult; /* result from the certificate verification */
curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */
void *fsslctxp; /* parameter for call back */
char *cert_type; /* format for certificate (default: PEM)*/
char *key; /* private key file name */
struct curl_blob *key_blob;
char *key_type; /* format for private key (default: PEM) */
char *key_passwd; /* plain text private key password */
BIT(certinfo); /* gather lots of certificate info */
BIT(falsestart);
BIT(enable_beast); /* allow this flaw for interoperability's sake */
BIT(no_revoke); /* disable SSL certificate revocation checks */
BIT(no_partialchain); /* don't accept partial certificate chains */
BIT(revoke_best_effort); /* ignore SSL revocation offline/missing revocation
list errors */
BIT(native_ca_store); /* use the native ca store of operating system */
BIT(auto_client_cert); /* automatically locate and use a client
certificate for authentication (Schannel) */
};
struct ssl_general_config {
size_t max_ssl_sessions; /* SSL session id cache size */
int ca_cache_timeout; /* Certificate store cache timeout (seconds) */
};
/* information stored about one single SSL session */
struct Curl_ssl_session {
char *name; /* host name for which this ID was used */
char *conn_to_host; /* host name for the connection (may be NULL) */
const char *scheme; /* protocol scheme used */
void *sessionid; /* as returned from the SSL layer */
size_t idsize; /* if known, otherwise 0 */
long age; /* just a number, the higher the more recent */
int remote_port; /* remote port */
int conn_to_port; /* remote port for the connection (may be -1) */
struct ssl_primary_config ssl_config; /* setup for this session */
};
#ifdef USE_WINDOWS_SSPI
#include "curl_sspi.h"
#endif
/* Struct used for Digest challenge-response authentication */
struct digestdata {
#if defined(USE_WINDOWS_SSPI)
BYTE *input_token;
size_t input_token_len;
CtxtHandle *http_context;
/* copy of user/passwd used to make the identity for http_context.
either may be NULL. */
char *user;
char *passwd;
#else
char *nonce;
char *cnonce;
char *realm;
char *opaque;
char *qop;
char *algorithm;
int nc; /* nonce count */
unsigned char algo;
BIT(stale); /* set true for re-negotiation */
BIT(userhash);
#endif
};
typedef enum {
NTLMSTATE_NONE,
NTLMSTATE_TYPE1,
NTLMSTATE_TYPE2,
NTLMSTATE_TYPE3,
NTLMSTATE_LAST
} curlntlm;
typedef enum {
GSS_AUTHNONE,
GSS_AUTHRECV,
GSS_AUTHSENT,
GSS_AUTHDONE,
GSS_AUTHSUCC
} curlnegotiate;
/* Struct used for GSSAPI (Kerberos V5) authentication */
#if defined(USE_KERBEROS5)
struct kerberos5data {
#if defined(USE_WINDOWS_SSPI)
CredHandle *credentials;
CtxtHandle *context;
TCHAR *spn;
SEC_WINNT_AUTH_IDENTITY identity;
SEC_WINNT_AUTH_IDENTITY *p_identity;
size_t token_max;
BYTE *output_token;
#else
gss_ctx_id_t context;
gss_name_t spn;
#endif
};
#endif
/* Struct used for SCRAM-SHA-1 authentication */
#ifdef USE_GSASL
#include <gsasl.h>
struct gsasldata {
Gsasl *ctx;
Gsasl_session *client;
};
#endif
/* Struct used for NTLM challenge-response authentication */
#if defined(USE_NTLM)
struct ntlmdata {
#ifdef USE_WINDOWS_SSPI
/* The sslContext is used for the Schannel bindings. The
* api is available on the Windows 7 SDK and later.
*/
#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS
CtxtHandle *sslContext;
#endif
CredHandle *credentials;
CtxtHandle *context;
SEC_WINNT_AUTH_IDENTITY identity;
SEC_WINNT_AUTH_IDENTITY *p_identity;
size_t token_max;
BYTE *output_token;
BYTE *input_token;
size_t input_token_len;
TCHAR *spn;
#else
unsigned int flags;
unsigned char nonce[8];
unsigned int target_info_len;
void *target_info; /* TargetInfo received in the ntlm type-2 message */
#if defined(NTLM_WB_ENABLED)
/* used for communication with Samba's winbind daemon helper ntlm_auth */
curl_socket_t ntlm_auth_hlpr_socket;
pid_t ntlm_auth_hlpr_pid;
char *challenge; /* The received base64 encoded ntlm type-2 message */
char *response; /* The generated base64 ntlm type-1/type-3 message */
#endif
#endif
};
#endif
/* Struct used for Negotiate (SPNEGO) authentication */
#ifdef USE_SPNEGO
struct negotiatedata {
#ifdef HAVE_GSSAPI
OM_uint32 status;
gss_ctx_id_t context;
gss_name_t spn;
gss_buffer_desc output_token;
#else
#ifdef USE_WINDOWS_SSPI
#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS
CtxtHandle *sslContext;
#endif
DWORD status;
CredHandle *credentials;
CtxtHandle *context;
SEC_WINNT_AUTH_IDENTITY identity;
SEC_WINNT_AUTH_IDENTITY *p_identity;
TCHAR *spn;
size_t token_max;
BYTE *output_token;
size_t output_token_length;
#endif
#endif
BIT(noauthpersist);
BIT(havenoauthpersist);
BIT(havenegdata);
BIT(havemultiplerequests);
};
#endif
#ifdef CURL_DISABLE_PROXY
#define CONN_IS_PROXIED(x) 0
#else
#define CONN_IS_PROXIED(x) x->bits.proxy
#endif
/*
* Boolean values that concerns this connection.
*/
struct ConnectBits {
#ifndef CURL_DISABLE_PROXY
BIT(httpproxy); /* if set, this transfer is done through an HTTP proxy */
BIT(socksproxy); /* if set, this transfer is done through a socks proxy */
BIT(proxy_user_passwd); /* user+password for the proxy? */
BIT(tunnel_proxy); /* if CONNECT is used to "tunnel" through the proxy.
This is implicit when SSL-protocols are used through
proxies, but can also be enabled explicitly by
apps */
BIT(proxy_connect_closed); /* TRUE if a proxy disconnected the connection
in a CONNECT request with auth, so that
libcurl should reconnect and continue. */
BIT(proxy); /* if set, this transfer is done through a proxy - any type */
#endif
/* always modify bits.close with the connclose() and connkeep() macros! */
BIT(close); /* if set, we close the connection after this request */
BIT(reuse); /* if set, this is a re-used connection */
BIT(altused); /* this is an alt-svc "redirect" */
BIT(conn_to_host); /* if set, this connection has a "connect to host"
that overrides the host in the URL */
BIT(conn_to_port); /* if set, this connection has a "connect to port"
that overrides the port in the URL (remote port) */
BIT(ipv6_ip); /* we communicate with a remote site specified with pure IPv6
IP address */
BIT(ipv6); /* we communicate with a site using an IPv6 address */
BIT(do_more); /* this is set TRUE if the ->curl_do_more() function is
supposed to be called, after ->curl_do() */
BIT(protoconnstart);/* the protocol layer has STARTED its operation after
the TCP layer connect */
BIT(retry); /* this connection is about to get closed and then
re-attempted at another connection. */
BIT(authneg); /* TRUE when the auth phase has started, which means
that we are creating a request with an auth header,
but it is not the final request in the auth
negotiation. */
#ifndef CURL_DISABLE_FTP
BIT(ftp_use_epsv); /* As set with CURLOPT_FTP_USE_EPSV, but if we find out
EPSV doesn't work we disable it for the forthcoming
requests */
BIT(ftp_use_eprt); /* As set with CURLOPT_FTP_USE_EPRT, but if we find out
EPRT doesn't work we disable it for the forthcoming
requests */
BIT(ftp_use_data_ssl); /* Enabled SSL for the data connection */
BIT(ftp_use_control_ssl); /* Enabled SSL for the control connection */
#endif
#ifndef CURL_DISABLE_NETRC
BIT(netrc); /* name+password provided by netrc */
#endif
BIT(bound); /* set true if bind() has already been done on this socket/
connection */
BIT(multiplex); /* connection is multiplexed */
BIT(tcp_fastopen); /* use TCP Fast Open */
BIT(tls_enable_alpn); /* TLS ALPN extension? */
#ifndef CURL_DISABLE_DOH
BIT(doh);
#endif
#ifdef USE_UNIX_SOCKETS
BIT(abstract_unix_socket);
#endif
BIT(tls_upgraded);
BIT(sock_accepted); /* TRUE if the SECONDARYSOCKET was created with
accept() */
BIT(parallel_connect); /* set TRUE when a parallel connect attempt has
started (happy eyeballs) */
};
struct hostname {
char *rawalloc; /* allocated "raw" version of the name */
char *encalloc; /* allocated IDN-encoded version of the name */
char *name; /* name to use internally, might be encoded, might be raw */
const char *dispname; /* name to display, as 'name' might be encoded */
};
/*
* Flags on the keepon member of the Curl_transfer_keeper
*/
#define KEEP_NONE 0
#define KEEP_RECV (1<<0) /* there is or may be data to read */
#define KEEP_SEND (1<<1) /* there is or may be data to write */
#define KEEP_RECV_HOLD (1<<2) /* when set, no reading should be done but there
might still be data to read */
#define KEEP_SEND_HOLD (1<<3) /* when set, no writing should be done but there
might still be data to write */
#define KEEP_RECV_PAUSE (1<<4) /* reading is paused */
#define KEEP_SEND_PAUSE (1<<5) /* writing is paused */
#define KEEP_RECVBITS (KEEP_RECV | KEEP_RECV_HOLD | KEEP_RECV_PAUSE)
#define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE)
#if defined(CURLRES_ASYNCH) || !defined(CURL_DISABLE_DOH)
#define USE_CURL_ASYNC
struct Curl_async {
char *hostname;
struct Curl_dns_entry *dns;
struct thread_data *tdata;
void *resolver; /* resolver state, if it is used in the URL state -
ares_channel e.g. */
int port;
int status; /* if done is TRUE, this is the status from the callback */
BIT(done); /* set TRUE when the lookup is complete */
};
#endif
#define FIRSTSOCKET 0
#define SECONDARYSOCKET 1
enum expect100 {
EXP100_SEND_DATA, /* enough waiting, just send the body now */
EXP100_AWAITING_CONTINUE, /* waiting for the 100 Continue header */
EXP100_SENDING_REQUEST, /* still sending the request but will wait for
the 100 header once done with the request */
EXP100_FAILED /* used on 417 Expectation Failed */
};
enum upgrade101 {
UPGR101_INIT, /* default state */
UPGR101_WS, /* upgrade to WebSockets requested */
UPGR101_H2, /* upgrade to HTTP/2 requested */
UPGR101_RECEIVED, /* 101 response received */
UPGR101_WORKING /* talking upgraded protocol */
};
enum doh_slots {
/* Explicit values for first two symbols so as to match hard-coded
* constants in existing code
*/
DOH_PROBE_SLOT_IPADDR_V4 = 0, /* make 'V4' stand out for readability */
DOH_PROBE_SLOT_IPADDR_V6 = 1, /* 'V6' likewise */
/* Space here for (possibly build-specific) additional slot definitions */
/* for example */
/* #ifdef WANT_DOH_FOOBAR_TXT */
/* DOH_PROBE_SLOT_FOOBAR_TXT, */
/* #endif */
/* AFTER all slot definitions, establish how many we have */
DOH_PROBE_SLOTS
};
/*
* Request specific data in the easy handle (Curl_easy). Previously,
* these members were on the connectdata struct but since a conn struct may
* now be shared between different Curl_easys, we store connection-specific
* data here. This struct only keeps stuff that's interesting for *this*
* request, as it will be cleared between multiple ones
*/
struct SingleRequest {
curl_off_t size; /* -1 if unknown at this point */
curl_off_t maxdownload; /* in bytes, the maximum amount of data to fetch,
-1 means unlimited */
curl_off_t bytecount; /* total number of bytes read */
curl_off_t writebytecount; /* number of bytes written */
curl_off_t headerbytecount; /* only count received headers */
curl_off_t deductheadercount; /* this amount of bytes doesn't count when we
check if anything has been transferred at
the end of a connection. We use this
counter to make only a 100 reply (without a
following second response code) result in a
CURLE_GOT_NOTHING error code */
curl_off_t pendingheader; /* this many bytes left to send is actually
header and not body */
struct curltime start; /* transfer started at this time */
struct curltime now; /* current time */
enum {
HEADER_NORMAL, /* no bad header at all */
HEADER_PARTHEADER, /* part of the chunk is a bad header, the rest
is normal data */
HEADER_ALLBAD /* all was believed to be header */
} badheader; /* the header was deemed bad and will be
written as body */
int headerline; /* counts header lines to better track the
first one */
char *str; /* within buf */
curl_off_t offset; /* possible resume offset read from the
Content-Range: header */
int httpcode; /* error code from the 'HTTP/1.? XXX' or
'RTSP/1.? XXX' line */
int keepon;
struct curltime start100; /* time stamp to wait for the 100 code from */
enum expect100 exp100; /* expect 100 continue state */
enum upgrade101 upgr101; /* 101 upgrade state */
/* Content unencoding stack. See sec 3.5, RFC2616. */
struct contenc_writer *writer_stack;
time_t timeofdoc;
long bodywrites;
char *location; /* This points to an allocated version of the Location:
header data */
char *newurl; /* Set to the new URL to use when a redirect or a retry is
wanted */
/* 'upload_present' is used to keep a byte counter of how much data there is
still left in the buffer, aimed for upload. */
ssize_t upload_present;
/* 'upload_fromhere' is used as a read-pointer when we uploaded parts of a
buffer, so the next read should read from where this pointer points to,
and the 'upload_present' contains the number of bytes available at this
position */
char *upload_fromhere;
/* Allocated protocol-specific data. Each protocol handler makes sure this
points to data it needs. */
union {
struct FILEPROTO *file;
struct FTP *ftp;
struct HTTP *http;
struct IMAP *imap;
struct ldapreqinfo *ldap;
struct MQTT *mqtt;
struct POP3 *pop3;
struct RTSP *rtsp;
struct smb_request *smb;
struct SMTP *smtp;
struct SSHPROTO *ssh;
struct TELNET *telnet;
} p;
#ifndef CURL_DISABLE_DOH
struct dohdata *doh; /* DoH specific data for this request */
#endif
unsigned char setcookies;
BIT(header); /* incoming data has HTTP header */
BIT(content_range); /* set TRUE if Content-Range: was found */
BIT(upload_done); /* set to TRUE when doing chunked transfer-encoding
upload and we're uploading the last chunk */
BIT(ignorebody); /* we read a response-body but we ignore it! */
BIT(http_bodyless); /* HTTP response status code is between 100 and 199,
204 or 304 */
BIT(chunk); /* if set, this is a chunked transfer-encoding */
BIT(ignore_cl); /* ignore content-length */
BIT(upload_chunky); /* set TRUE if we are doing chunked transfer-encoding
on upload */
BIT(getheader); /* TRUE if header parsing is wanted */
BIT(forbidchunk); /* used only to explicitly forbid chunk-upload for
specific upload buffers. See readmoredata() in http.c
for details. */
BIT(no_body); /* the response has no body */
};
/*
* Specific protocol handler.
*/
struct Curl_handler {
const char *scheme; /* URL scheme name. */
/* Complement to setup_connection_internals(). This is done before the
transfer "owns" the connection. */
CURLcode (*setup_connection)(struct Curl_easy *data,
struct connectdata *conn);
/* These two functions MUST be set to be protocol dependent */
CURLcode (*do_it)(struct Curl_easy *data, bool *done);
CURLcode (*done)(struct Curl_easy *, CURLcode, bool);
/* If the curl_do() function is better made in two halves, this
* curl_do_more() function will be called afterwards, if set. For example
* for doing the FTP stuff after the PASV/PORT command.
*/
CURLcode (*do_more)(struct Curl_easy *, int *);
/* This function *MAY* be set to a protocol-dependent function that is run
* after the connect() and everything is done, as a step in the connection.
* The 'done' pointer points to a bool that should be set to TRUE if the
* function completes before return. If it doesn't complete, the caller
* should call the curl_connecting() function until it is.
*/
CURLcode (*connect_it)(struct Curl_easy *data, bool *done);
/* See above. */
CURLcode (*connecting)(struct Curl_easy *data, bool *done);
CURLcode (*doing)(struct Curl_easy *data, bool *done);
/* Called from the multi interface during the PROTOCONNECT phase, and it
should then return a proper fd set */
int (*proto_getsock)(struct Curl_easy *data,
struct connectdata *conn, curl_socket_t *socks);
/* Called from the multi interface during the DOING phase, and it should
then return a proper fd set */
int (*doing_getsock)(struct Curl_easy *data,
struct connectdata *conn, curl_socket_t *socks);
/* Called from the multi interface during the DO_MORE phase, and it should
then return a proper fd set */
int (*domore_getsock)(struct Curl_easy *data,
struct connectdata *conn, curl_socket_t *socks);
/* Called from the multi interface during the DO_DONE, PERFORM and
WAITPERFORM phases, and it should then return a proper fd set. Not setting
this will make libcurl use the generic default one. */
int (*perform_getsock)(struct Curl_easy *data,
struct connectdata *conn, curl_socket_t *socks);
/* This function *MAY* be set to a protocol-dependent function that is run
* by the curl_disconnect(), as a step in the disconnection. If the handler
* is called because the connection has been considered dead,
* dead_connection is set to TRUE. The connection is (again) associated with
* the transfer here.
*/
CURLcode (*disconnect)(struct Curl_easy *, struct connectdata *,
bool dead_connection);
/* If used, this function gets called from transfer.c:readwrite_data() to
allow the protocol to do extra reads/writes */
CURLcode (*readwrite)(struct Curl_easy *data, struct connectdata *conn,
ssize_t *nread, bool *readmore);
/* This function can perform various checks on the connection. See
CONNCHECK_* for more information about the checks that can be performed,
and CONNRESULT_* for the results that can be returned. */
unsigned int (*connection_check)(struct Curl_easy *data,
struct connectdata *conn,
unsigned int checks_to_perform);
/* attach() attaches this transfer to this connection */
void (*attach)(struct Curl_easy *data, struct connectdata *conn);
int defport; /* Default port. */
curl_prot_t protocol; /* See CURLPROTO_* - this needs to be the single
specific protocol bit */
curl_prot_t family; /* single bit for protocol family; basically the
non-TLS name of the protocol this is */
unsigned int flags; /* Extra particular characteristics, see PROTOPT_* */
};
#define PROTOPT_NONE 0 /* nothing extra */
#define PROTOPT_SSL (1<<0) /* uses SSL */
#define PROTOPT_DUAL (1<<1) /* this protocol uses two connections */
#define PROTOPT_CLOSEACTION (1<<2) /* need action before socket close */
/* some protocols will have to call the underlying functions without regard to
what exact state the socket signals. IE even if the socket says "readable",
the send function might need to be called while uploading, or vice versa.
*/
#define PROTOPT_DIRLOCK (1<<3)
#define PROTOPT_NONETWORK (1<<4) /* protocol doesn't use the network! */
#define PROTOPT_NEEDSPWD (1<<5) /* needs a password, and if none is set it
gets a default */
#define PROTOPT_NOURLQUERY (1<<6) /* protocol can't handle
url query strings (?foo=bar) ! */
#define PROTOPT_CREDSPERREQUEST (1<<7) /* requires login credentials per
request instead of per connection */
#define PROTOPT_ALPN (1<<8) /* set ALPN for this */
/* (1<<9) was PROTOPT_STREAM, now free */
#define PROTOPT_URLOPTIONS (1<<10) /* allow options part in the userinfo field
of the URL */
#define PROTOPT_PROXY_AS_HTTP (1<<11) /* allow this non-HTTP scheme over a
HTTP proxy as HTTP proxies may know
this protocol and act as a gateway */
#define PROTOPT_WILDCARD (1<<12) /* protocol supports wildcard matching */
#define PROTOPT_USERPWDCTRL (1<<13) /* Allow "control bytes" (< 32 ascii) in
user name and password */
#define PROTOPT_NOTCPPROXY (1<<14) /* this protocol can't proxy over TCP */
#define CONNCHECK_NONE 0 /* No checks */
#define CONNCHECK_ISDEAD (1<<0) /* Check if the connection is dead. */
#define CONNCHECK_KEEPALIVE (1<<1) /* Perform any keepalive function. */
#define CONNRESULT_NONE 0 /* No extra information. */
#define CONNRESULT_DEAD (1<<0) /* The connection is dead. */
struct proxy_info {
struct hostname host;
int port;
unsigned char proxytype; /* curl_proxytype: what kind of proxy that is in
use */
char *user; /* proxy user name string, allocated */
char *passwd; /* proxy password string, allocated */
};
struct ldapconninfo;
#define TRNSPRT_TCP 3
#define TRNSPRT_UDP 4
#define TRNSPRT_QUIC 5
#define TRNSPRT_UNIX 6
/*
* The connectdata struct contains all fields and variables that should be
* unique for an entire connection.
*/
struct connectdata {
struct Curl_llist_element bundle_node; /* conncache */
/* chunk is for HTTP chunked encoding, but is in the general connectdata
struct only because we can do just about any protocol through an HTTP
proxy and an HTTP proxy may in fact respond using chunked encoding */
struct Curl_chunker chunk;
curl_closesocket_callback fclosesocket; /* function closing the socket(s) */
void *closesocket_client;
/* This is used by the connection cache logic. If this returns TRUE, this
handle is still used by one or more easy handles and can only used by any
other easy handle without careful consideration (== only for
multiplexing) and it cannot be used by another multi handle! */
#define CONN_INUSE(c) ((c)->easyq.size)
/**** Fields set when inited and not modified again */
long connection_id; /* Contains a unique number to make it easier to
track the connections in the log output */
/* 'dns_entry' is the particular host we use. This points to an entry in the
DNS cache and it will not get pruned while locked. It gets unlocked in
multi_done(). This entry will be NULL if the connection is re-used as then
there is no name resolve done. */
struct Curl_dns_entry *dns_entry;
/* 'remote_addr' is the particular IP we connected to. it is owned, set
* and NULLed by the connected socket filter (if there is one). */
const struct Curl_sockaddr_ex *remote_addr;
struct hostname host;
char *hostname_resolve; /* host name to resolve to address, allocated */
char *secondaryhostname; /* secondary socket host name (ftp) */
struct hostname conn_to_host; /* the host to connect to. valid only if
bits.conn_to_host is set */
#ifndef CURL_DISABLE_PROXY
struct proxy_info socks_proxy;
struct proxy_info http_proxy;
#endif
/* 'primary_ip' and 'primary_port' get filled with peer's numerical
ip address and port number whenever an outgoing connection is
*attempted* from the primary socket to a remote address. When more
than one address is tried for a connection these will hold data
for the last attempt. When the connection is actually established
these are updated with data which comes directly from the socket. */
char primary_ip[MAX_IPADR_LEN];
char *user; /* user name string, allocated */
char *passwd; /* password string, allocated */
char *options; /* options string, allocated */
char *sasl_authzid; /* authorization identity string, allocated */
char *oauth_bearer; /* OAUTH2 bearer, allocated */
struct curltime now; /* "current" time */
struct curltime created; /* creation time */
struct curltime lastused; /* when returned to the connection cache */
curl_socket_t sock[2]; /* two sockets, the second is used for the data
transfer when doing FTP */
Curl_recv *recv[2];
Curl_send *send[2];
struct Curl_cfilter *cfilter[2]; /* connection filters */
struct ssl_primary_config ssl_config;
#ifndef CURL_DISABLE_PROXY
struct ssl_primary_config proxy_ssl_config;
#endif
struct ConnectBits bits; /* various state-flags for this connection */
const struct Curl_handler *handler; /* Connection's protocol handler */
const struct Curl_handler *given; /* The protocol first given */
/* Protocols can use a custom keepalive mechanism to keep connections alive.
This allows those protocols to track the last time the keepalive mechanism
was used on this connection. */
struct curltime keepalive;
/**** curl_get() phase fields */
curl_socket_t sockfd; /* socket to read from or CURL_SOCKET_BAD */
curl_socket_t writesockfd; /* socket to write to, it may very
well be the same we read from.
CURL_SOCKET_BAD disables */
#ifdef HAVE_GSSAPI
BIT(sec_complete); /* if Kerberos is enabled for this connection */
unsigned char command_prot; /* enum protection_level */
unsigned char data_prot; /* enum protection_level */
unsigned char request_data_prot; /* enum protection_level */
size_t buffer_size;
struct krb5buffer in_buffer;
void *app_data;
const struct Curl_sec_client_mech *mech;
struct sockaddr_in local_addr;
#endif
#if defined(USE_KERBEROS5) /* Consider moving some of the above GSS-API */
struct kerberos5data krb5; /* variables into the structure definition, */
#endif /* however, some of them are ftp specific. */
struct Curl_llist easyq; /* List of easy handles using this connection */
curl_seek_callback seek_func; /* function that seeks the input */
void *seek_client; /* pointer to pass to the seek() above */
/*************** Request - specific items ************/
#if defined(USE_WINDOWS_SSPI) && defined(SECPKG_ATTR_ENDPOINT_BINDINGS)
CtxtHandle *sslContext;
#endif
#ifdef USE_GSASL
struct gsasldata gsasl;
#endif
#if defined(USE_NTLM)
curlntlm http_ntlm_state;
curlntlm proxy_ntlm_state;
struct ntlmdata ntlm; /* NTLM differs from other authentication schemes
because it authenticates connections, not
single requests! */
struct ntlmdata proxyntlm; /* NTLM data for proxy */
#endif
#ifdef USE_SPNEGO
curlnegotiate http_negotiate_state;
curlnegotiate proxy_negotiate_state;
struct negotiatedata negotiate; /* state data for host Negotiate auth */
struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */
#endif
#ifndef CURL_DISABLE_HTTP
/* for chunked-encoded trailer */
struct dynbuf trailer;
#endif
union {
#ifndef CURL_DISABLE_FTP
struct ftp_conn ftpc;
#endif
#ifdef USE_SSH
struct ssh_conn sshc;
#endif
#ifndef CURL_DISABLE_TFTP
struct tftp_state_data *tftpc;
#endif
#ifndef CURL_DISABLE_IMAP
struct imap_conn imapc;
#endif