/* * Curl_pp_statemach() */ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block, bool disconnecting) { struct connectdata *conn = pp->conn; curl_socket_t sock = conn->sock[FIRSTSOCKET]; int rc; time_t interval_ms; time_t timeout_ms = Curl_pp_state_timeout(pp, disconnecting); struct Curl_easy *data = conn->data; CURLcode result = CURLE_OK; if(timeout_ms <= 0) { failf(data, "server response timeout"); return CURLE_OPERATION_TIMEDOUT; /* already too little time */ } if(block) { interval_ms = 1000; /* use 1 second timeout intervals */ if(timeout_ms < interval_ms) interval_ms = timeout_ms; } else interval_ms = 0; /* immediate */ if(Curl_ssl_data_pending(conn, FIRSTSOCKET)) rc = 1; else if(Curl_pp_moredata(pp)) /* We are receiving and there is data in the cache so just read it */ rc = 1; else if(!pp->sendleft && Curl_ssl_data_pending(conn, FIRSTSOCKET)) /* We are receiving and there is data ready in the SSL library */ rc = 1; else rc = Curl_socket_check(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */ CURL_SOCKET_BAD, pp->sendleft?sock:CURL_SOCKET_BAD, /* writing */ interval_ms); if(block) { /* if we didn't wait, we don't have to spend time on this now */ if(Curl_pgrsUpdate(conn)) result = CURLE_ABORTED_BY_CALLBACK; else result = Curl_speedcheck(data, Curl_now()); if(result) return result; } if(rc == -1) { failf(data, "select/poll error"); result = CURLE_OUT_OF_MEMORY; } else if(rc) result = pp->statemach_act(conn); return result; }
static CURLcode smtp_statemach_act(struct connectdata *conn) { CURLcode result = CURLE_OK; curl_socket_t sock = conn->sock[FIRSTSOCKET]; struct Curl_easy *data = conn->data; int smtpcode; struct smtp_conn *smtpc = &conn->proto.smtpc; struct pingpong *pp = &smtpc->pp; size_t nread = 0; /* Busy upgrading the connection; right now all I/O is SSL/TLS, not SMTP */ if(smtpc->state == SMTP_UPGRADETLS) return smtp_perform_upgrade_tls(conn); /* Flush any data that needs to be sent */ if(pp->sendleft) return Curl_pp_flushsend(pp); do { /* Read the response from the server */ result = Curl_pp_readresp(sock, pp, &smtpcode, &nread); if(result) return result; /* Store the latest response for later retrieval if necessary */ if(smtpc->state != SMTP_QUIT && smtpcode != 1) data->info.httpcode = smtpcode; if(!smtpcode) break; /* We have now received a full SMTP server response */ switch(smtpc->state) { case SMTP_SERVERGREET: result = smtp_state_servergreet_resp(conn, smtpcode, smtpc->state); break; case SMTP_EHLO: result = smtp_state_ehlo_resp(conn, smtpcode, smtpc->state); break; case SMTP_HELO: result = smtp_state_helo_resp(conn, smtpcode, smtpc->state); break; case SMTP_STARTTLS: result = smtp_state_starttls_resp(conn, smtpcode, smtpc->state); break; case SMTP_AUTH: result = smtp_state_auth_resp(conn, smtpcode, smtpc->state); break; case SMTP_COMMAND: result = smtp_state_command_resp(conn, smtpcode, smtpc->state); break; case SMTP_MAIL: result = smtp_state_mail_resp(conn, smtpcode, smtpc->state); break; case SMTP_RCPT: result = smtp_state_rcpt_resp(conn, smtpcode, smtpc->state); break; case SMTP_DATA: result = smtp_state_data_resp(conn, smtpcode, smtpc->state); break; case SMTP_POSTDATA: result = smtp_state_postdata_resp(conn, smtpcode, smtpc->state); break; case SMTP_QUIT: /* fallthrough, just stop! */ default: /* internal error */ state(conn, SMTP_STOP); break; } } while(!result && smtpc->state != SMTP_STOP && Curl_pp_moredata(pp)); return result; }
static CURLcode pop3_statemach_act(struct connectdata *conn) { CURLcode result = CURLE_OK; curl_socket_t sock = conn->sock[FIRSTSOCKET]; int pop3code; struct pop3_conn *pop3c = &conn->proto.pop3c; struct pingpong *pp = &pop3c->pp; size_t nread = 0; /* Busy upgrading the connection; right now all I/O is SSL/TLS, not POP3 */ if(pop3c->state == POP3_UPGRADETLS) return pop3_perform_upgrade_tls(conn); /* Flush any data that needs to be sent */ if(pp->sendleft) return Curl_pp_flushsend(pp); do { /* Read the response from the server */ result = Curl_pp_readresp(sock, pp, &pop3code, &nread); if(result) return result; if(!pop3code) break; /* We have now received a full POP3 server response */ switch(pop3c->state) { case POP3_SERVERGREET: result = pop3_state_servergreet_resp(conn, pop3code, pop3c->state); break; case POP3_CAPA: result = pop3_state_capa_resp(conn, pop3code, pop3c->state); break; case POP3_STARTTLS: result = pop3_state_starttls_resp(conn, pop3code, pop3c->state); break; case POP3_AUTH: result = pop3_state_auth_resp(conn, pop3code, pop3c->state); break; #ifndef CURL_DISABLE_CRYPTO_AUTH case POP3_APOP: result = pop3_state_apop_resp(conn, pop3code, pop3c->state); break; #endif case POP3_USER: result = pop3_state_user_resp(conn, pop3code, pop3c->state); break; case POP3_PASS: result = pop3_state_pass_resp(conn, pop3code, pop3c->state); break; case POP3_COMMAND: result = pop3_state_command_resp(conn, pop3code, pop3c->state); break; case POP3_QUIT: /* fallthrough, just stop! */ default: /* internal error */ state(conn, POP3_STOP); break; } } while(!result && pop3c->state != POP3_STOP && Curl_pp_moredata(pp)); return result; }