/* Open the connection to the server. */ int mu_nntp_connect (mu_nntp_t nntp) { int status; /* Sanity checks. */ if (nntp == NULL) return EINVAL; /* A networking stack. */ if (nntp->carrier == NULL) return EINVAL; /* Enter the nntp state machine, and boogy */ switch (nntp->state) { default: /* FALLTHROUGH */ /* If nntp was in an error state going through here should clear it. */ case MU_NNTP_NO_STATE: status = mu_nntp_disconnect (nntp); MU_NNTP_CHECK_EAGAIN (nntp, status); nntp->state = MU_NNTP_CONNECT; case MU_NNTP_CONNECT: /* Establish the connection. */ status = mu_stream_open (nntp->carrier); MU_NNTP_CHECK_EAGAIN (nntp, status); nntp->acknowledge = 0; nntp->state = MU_NNTP_GREETINGS; case MU_NNTP_GREETINGS: /* Get the greetings. */ { size_t len = 0; int code; status = mu_nntp_response (nntp, NULL, 0, &len); MU_NNTP_CHECK_EAGAIN (nntp, status); mu_nntp_debug_ack (nntp); /* 200 Service available, posting allowed */ /* 201 Servie available, posting prohibited */ code = mu_nntp_response_code(nntp); if (code != MU_NNTP_RESP_CODE_POSTING_ALLOWED && code != MU_NNTP_RESP_CODE_POSTING_PROHIBITED) { mu_stream_close (nntp->carrier); nntp->state = MU_NNTP_NO_STATE; return EACCES; } nntp->state = MU_NNTP_NO_STATE; } } /* End AUTHORISATION state. */ return status; }
int mu_nntp_help (mu_nntp_t nntp, mu_stream_t *pstream) { int status; if (nntp == NULL) return EINVAL; if (pstream == NULL) return MU_ERR_OUT_PTR_NULL; switch (nntp->state) { case MU_NNTP_NO_STATE: status = mu_nntp_writeline (nntp, "HELP\r\n"); MU_NNTP_CHECK_ERROR (nntp, status); mu_nntp_debug_cmd (nntp); nntp->state = MU_NNTP_HELP; case MU_NNTP_HELP: status = mu_nntp_send (nntp); MU_NNTP_CHECK_EAGAIN (nntp, status); nntp->acknowledge = 0; nntp->state = MU_NNTP_HELP_ACK; case MU_NNTP_HELP_ACK: status = mu_nntp_response (nntp, NULL, 0, NULL); MU_NNTP_CHECK_EAGAIN (nntp, status); mu_nntp_debug_ack (nntp); MU_NNTP_CHECK_CODE (nntp, MU_NNTP_RESP_CODE_HELP_FOLLOW); nntp->state = MU_NNTP_HELP_RX; case MU_NNTP_HELP_RX: status = mu_nntp_stream_create (nntp, pstream); MU_NNTP_CHECK_ERROR (nntp, status); break; /* They must deal with the error first by reopening. */ case MU_NNTP_ERROR: status = ECANCELED; break; default: status = EINPROGRESS; } return status; }
/* LIST EXTENSIONS command, return an iterator that contains the result. It is the responsability of the caller to destroy the iterator(mu_iterator_destroy). */ int mu_nntp_list_extensions (mu_nntp_t nntp, mu_iterator_t *piterator) { int status = 0; if (nntp == NULL) return EINVAL; if (piterator == NULL) return MU_ERR_OUT_PTR_NULL; switch (nntp->state) { case MU_NNTP_NO_STATE: status = mu_nntp_writeline (nntp, "LIST EXTENSIONS\r\n"); MU_NNTP_CHECK_ERROR (nntp, status); mu_nntp_debug_cmd (nntp); nntp->state = MU_NNTP_LIST_EXTENSIONS; case MU_NNTP_LIST_EXTENSIONS: status = mu_nntp_send (nntp); MU_NNTP_CHECK_EAGAIN (nntp, status); nntp->acknowledge = 0; nntp->state = MU_NNTP_LIST_EXTENSIONS_ACK; case MU_NNTP_LIST_EXTENSIONS_ACK: status = mu_nntp_response (nntp, NULL, 0, NULL); MU_NNTP_CHECK_EAGAIN (nntp, status); mu_nntp_debug_ack (nntp); MU_NNTP_CHECK_CODE (nntp, MU_NNTP_RESP_CODE_EXTENSIONS_FOLLOW); status = mu_nntp_iterator_create (nntp, piterator); MU_NNTP_CHECK_ERROR(nntp, status); nntp->state = MU_NNTP_LIST_EXTENSIONS_RX; case MU_NNTP_LIST_EXTENSIONS_RX: break; /* They must deal with the error first by reopening. */ case MU_NNTP_ERROR: status = ECANCELED; break; default: status = EINPROGRESS; } return status; }