113498266Sopenharmony_ci#ifndef HEADER_CURL_PINGPONG_H 213498266Sopenharmony_ci#define HEADER_CURL_PINGPONG_H 313498266Sopenharmony_ci/*************************************************************************** 413498266Sopenharmony_ci * _ _ ____ _ 513498266Sopenharmony_ci * Project ___| | | | _ \| | 613498266Sopenharmony_ci * / __| | | | |_) | | 713498266Sopenharmony_ci * | (__| |_| | _ <| |___ 813498266Sopenharmony_ci * \___|\___/|_| \_\_____| 913498266Sopenharmony_ci * 1013498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 1113498266Sopenharmony_ci * 1213498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which 1313498266Sopenharmony_ci * you should have received as part of this distribution. The terms 1413498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html. 1513498266Sopenharmony_ci * 1613498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell 1713498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is 1813498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file. 1913498266Sopenharmony_ci * 2013498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 2113498266Sopenharmony_ci * KIND, either express or implied. 2213498266Sopenharmony_ci * 2313498266Sopenharmony_ci * SPDX-License-Identifier: curl 2413498266Sopenharmony_ci * 2513498266Sopenharmony_ci ***************************************************************************/ 2613498266Sopenharmony_ci 2713498266Sopenharmony_ci#include "curl_setup.h" 2813498266Sopenharmony_ci 2913498266Sopenharmony_ci#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_FTP) || \ 3013498266Sopenharmony_ci !defined(CURL_DISABLE_POP3) || !defined(CURL_DISABLE_SMTP) 3113498266Sopenharmony_ci#define USE_PINGPONG 3213498266Sopenharmony_ci#endif 3313498266Sopenharmony_ci 3413498266Sopenharmony_ci/* forward-declaration, this is defined in urldata.h */ 3513498266Sopenharmony_cistruct connectdata; 3613498266Sopenharmony_ci 3713498266Sopenharmony_citypedef enum { 3813498266Sopenharmony_ci PPTRANSFER_BODY, /* yes do transfer a body */ 3913498266Sopenharmony_ci PPTRANSFER_INFO, /* do still go through to get info/headers */ 4013498266Sopenharmony_ci PPTRANSFER_NONE /* don't get anything and don't get info */ 4113498266Sopenharmony_ci} curl_pp_transfer; 4213498266Sopenharmony_ci 4313498266Sopenharmony_ci/* 4413498266Sopenharmony_ci * 'pingpong' is the generic struct used for protocols doing server<->client 4513498266Sopenharmony_ci * conversations in a back-and-forth style such as FTP, IMAP, POP3, SMTP etc. 4613498266Sopenharmony_ci * 4713498266Sopenharmony_ci * It holds response cache and non-blocking sending data. 4813498266Sopenharmony_ci */ 4913498266Sopenharmony_cistruct pingpong { 5013498266Sopenharmony_ci size_t nread_resp; /* number of bytes currently read of a server response */ 5113498266Sopenharmony_ci bool pending_resp; /* set TRUE when a server response is pending or in 5213498266Sopenharmony_ci progress, and is cleared once the last response is 5313498266Sopenharmony_ci read */ 5413498266Sopenharmony_ci char *sendthis; /* pointer to a buffer that is to be sent to the server */ 5513498266Sopenharmony_ci size_t sendleft; /* number of bytes left to send from the sendthis buffer */ 5613498266Sopenharmony_ci size_t sendsize; /* total size of the sendthis buffer */ 5713498266Sopenharmony_ci struct curltime response; /* set to Curl_now() when a command has been sent 5813498266Sopenharmony_ci off, used to time-out response reading */ 5913498266Sopenharmony_ci timediff_t response_time; /* When no timeout is given, this is the amount of 6013498266Sopenharmony_ci milliseconds we await for a server response. */ 6113498266Sopenharmony_ci struct dynbuf sendbuf; 6213498266Sopenharmony_ci struct dynbuf recvbuf; 6313498266Sopenharmony_ci size_t overflow; /* number of bytes left after a final response line */ 6413498266Sopenharmony_ci size_t nfinal; /* number of bytes in the final response line, which 6513498266Sopenharmony_ci after a match is first in the receice buffer */ 6613498266Sopenharmony_ci 6713498266Sopenharmony_ci /* Function pointers the protocols MUST implement and provide for the 6813498266Sopenharmony_ci pingpong layer to function */ 6913498266Sopenharmony_ci 7013498266Sopenharmony_ci CURLcode (*statemachine)(struct Curl_easy *data, struct connectdata *conn); 7113498266Sopenharmony_ci bool (*endofresp)(struct Curl_easy *data, struct connectdata *conn, 7213498266Sopenharmony_ci char *ptr, size_t len, int *code); 7313498266Sopenharmony_ci}; 7413498266Sopenharmony_ci 7513498266Sopenharmony_ci#define PINGPONG_SETUP(pp,s,e) \ 7613498266Sopenharmony_ci do { \ 7713498266Sopenharmony_ci pp->response_time = RESP_TIMEOUT; \ 7813498266Sopenharmony_ci pp->statemachine = s; \ 7913498266Sopenharmony_ci pp->endofresp = e; \ 8013498266Sopenharmony_ci } while(0) 8113498266Sopenharmony_ci 8213498266Sopenharmony_ci/* 8313498266Sopenharmony_ci * Curl_pp_statemach() 8413498266Sopenharmony_ci * 8513498266Sopenharmony_ci * called repeatedly until done. Set 'wait' to make it wait a while on the 8613498266Sopenharmony_ci * socket if there's no traffic. 8713498266Sopenharmony_ci */ 8813498266Sopenharmony_ciCURLcode Curl_pp_statemach(struct Curl_easy *data, struct pingpong *pp, 8913498266Sopenharmony_ci bool block, bool disconnecting); 9013498266Sopenharmony_ci 9113498266Sopenharmony_ci/* initialize stuff to prepare for reading a fresh new response */ 9213498266Sopenharmony_civoid Curl_pp_init(struct pingpong *pp); 9313498266Sopenharmony_ci 9413498266Sopenharmony_ci/* Returns timeout in ms. 0 or negative number means the timeout has already 9513498266Sopenharmony_ci triggered */ 9613498266Sopenharmony_citimediff_t Curl_pp_state_timeout(struct Curl_easy *data, 9713498266Sopenharmony_ci struct pingpong *pp, bool disconnecting); 9813498266Sopenharmony_ci 9913498266Sopenharmony_ci 10013498266Sopenharmony_ci/*********************************************************************** 10113498266Sopenharmony_ci * 10213498266Sopenharmony_ci * Curl_pp_sendf() 10313498266Sopenharmony_ci * 10413498266Sopenharmony_ci * Send the formatted string as a command to a pingpong server. Note that 10513498266Sopenharmony_ci * the string should not have any CRLF appended, as this function will 10613498266Sopenharmony_ci * append the necessary things itself. 10713498266Sopenharmony_ci * 10813498266Sopenharmony_ci * made to never block 10913498266Sopenharmony_ci */ 11013498266Sopenharmony_ciCURLcode Curl_pp_sendf(struct Curl_easy *data, 11113498266Sopenharmony_ci struct pingpong *pp, 11213498266Sopenharmony_ci const char *fmt, ...) CURL_PRINTF(3, 4); 11313498266Sopenharmony_ci 11413498266Sopenharmony_ci/*********************************************************************** 11513498266Sopenharmony_ci * 11613498266Sopenharmony_ci * Curl_pp_vsendf() 11713498266Sopenharmony_ci * 11813498266Sopenharmony_ci * Send the formatted string as a command to a pingpong server. Note that 11913498266Sopenharmony_ci * the string should not have any CRLF appended, as this function will 12013498266Sopenharmony_ci * append the necessary things itself. 12113498266Sopenharmony_ci * 12213498266Sopenharmony_ci * made to never block 12313498266Sopenharmony_ci */ 12413498266Sopenharmony_ciCURLcode Curl_pp_vsendf(struct Curl_easy *data, 12513498266Sopenharmony_ci struct pingpong *pp, 12613498266Sopenharmony_ci const char *fmt, 12713498266Sopenharmony_ci va_list args) CURL_PRINTF(3, 0); 12813498266Sopenharmony_ci 12913498266Sopenharmony_ci/* 13013498266Sopenharmony_ci * Curl_pp_readresp() 13113498266Sopenharmony_ci * 13213498266Sopenharmony_ci * Reads a piece of a server response. 13313498266Sopenharmony_ci */ 13413498266Sopenharmony_ciCURLcode Curl_pp_readresp(struct Curl_easy *data, 13513498266Sopenharmony_ci curl_socket_t sockfd, 13613498266Sopenharmony_ci struct pingpong *pp, 13713498266Sopenharmony_ci int *code, /* return the server code if done */ 13813498266Sopenharmony_ci size_t *size); /* size of the response */ 13913498266Sopenharmony_ci 14013498266Sopenharmony_ci 14113498266Sopenharmony_ciCURLcode Curl_pp_flushsend(struct Curl_easy *data, 14213498266Sopenharmony_ci struct pingpong *pp); 14313498266Sopenharmony_ci 14413498266Sopenharmony_ci/* call this when a pingpong connection is disconnected */ 14513498266Sopenharmony_ciCURLcode Curl_pp_disconnect(struct pingpong *pp); 14613498266Sopenharmony_ci 14713498266Sopenharmony_ciint Curl_pp_getsock(struct Curl_easy *data, struct pingpong *pp, 14813498266Sopenharmony_ci curl_socket_t *socks); 14913498266Sopenharmony_ci 15013498266Sopenharmony_ci 15113498266Sopenharmony_ci/*********************************************************************** 15213498266Sopenharmony_ci * 15313498266Sopenharmony_ci * Curl_pp_moredata() 15413498266Sopenharmony_ci * 15513498266Sopenharmony_ci * Returns whether there are still more data in the cache and so a call 15613498266Sopenharmony_ci * to Curl_pp_readresp() will not block. 15713498266Sopenharmony_ci */ 15813498266Sopenharmony_cibool Curl_pp_moredata(struct pingpong *pp); 15913498266Sopenharmony_ci 16013498266Sopenharmony_ci#endif /* HEADER_CURL_PINGPONG_H */ 161