/*
 * Copyright (C) 1994-2018 Altair Engineering, Inc.
 * For more information, contact Altair at www.altair.com.
 *
 * This file is part of the PBS Professional ("PBS Pro") software.
 *
 * Open Source License Information:
 *
 * PBS Pro is free software. You can redistribute it and/or modify it under the
 * terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any
 * later version.
 *
 * PBS Pro is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Commercial License Information:
 *
 * For a copy of the commercial license terms and conditions,
 * go to: (http://www.pbspro.com/UserArea/agreement.html)
 * or contact the Altair Legal Department.
 *
 * Altair’s dual-license business model allows companies, individuals, and
 * organizations to create proprietary derivative works of PBS Pro and
 * distribute them - whether embedded or bundled with other software -
 * under a commercial license agreement.
 *
 * Use of Altair’s trademarks, including but not limited to "PBS™",
 * "PBS Professional®", and "PBS Pro™" and Altair’s logos is subject to Altair's
 * trademark licensing policies.
 *
 */


/**
 * @file	dec_rpys.c
 * @brief
 * decode_DIS_replySvr() - decode a Batch Protocol Reply Structure for Server
 *
 *	This routine decodes a batch reply into the form used by server.
 *	The only difference between this and the command version is on status
 *	replies.  For the server,  the attributes are decoded into a list of
 *	server svrattrl structures rather than a commands's attrl.
 *
 * 	batch_reply structure defined in libpbs.h, it must be allocated
 *	by the caller.
 */

#include <pbs_config.h>   /* the master config generated by configure */

#include <sys/types.h>
#include <stdlib.h>
#include "libpbs.h"
#include "list_link.h"
#include "dis.h"

/**
 * @brief
 *	-decode a Batch Protocol Reply Structure for Server
 *
 * @par Functionality:
 *	This routine decodes a batch reply into the form used by server.
 *      The only difference between this and the command version is on status
 *      replies.  For the server,  the attributes are decoded into a list of
 *      server svrattrl structures rather than a commands's attrl.
 *
 * @param[in] sock - socket descriptor
 * @param[in] reply - pointer to batch_reply structure
 *
 * @par	Note:
 *	batch_reply structure defined in libpbs.h, it must be allocated
 *      by the caller.
 *
 * @return	int
 * @retval	0	success
 * @retval	!0	error
 *
 */
int
decode_DIS_replySvr(int sock, struct batch_reply *reply)
{
	int		      ct;
	int		      i;
	struct brp_select    *psel;
	struct brp_select   **pselx;
	struct brp_status    *pstsvr;
	int		      rc = 0;
	size_t		      txtlen;

	/* first decode "header" consisting of protocol type and version */

	i = disrui(sock, &rc);
	if (rc != 0) return rc;
	if (i != PBS_BATCH_PROT_TYPE) return DIS_PROTO;
	i = disrui(sock, &rc);
	if (rc != 0) return rc;
	if (i != PBS_BATCH_PROT_VER) return DIS_PROTO;

	/* next decode code, auxcode and choice (union type identifier) */

	reply->brp_code    = disrsi(sock, &rc);
	if (rc) return rc;
	reply->brp_auxcode = disrsi(sock, &rc);
	if (rc) return rc;
	reply->brp_choice  = disrui(sock, &rc);
	if (rc) return rc;


	switch (reply->brp_choice) {

		case BATCH_REPLY_CHOICE_NULL:
			break;	/* no more to do */

		case BATCH_REPLY_CHOICE_Queue:
		case BATCH_REPLY_CHOICE_RdytoCom:
		case BATCH_REPLY_CHOICE_Commit:
			rc = disrfst(sock, PBS_MAXSVRJOBID+1, reply->brp_un.brp_jid);
			if (rc)
				return (rc);
			break;

		case BATCH_REPLY_CHOICE_Select:

			/* have to get count of number of strings first */

			reply->brp_un.brp_select = NULL;
			pselx = &reply->brp_un.brp_select;
			ct = disrui(sock, &rc);
			if (rc) return rc;

			while (ct--) {
				psel = (struct brp_select *)malloc(sizeof(struct brp_select));
				if (psel == 0) return DIS_NOMALLOC;
				psel->brp_next = NULL;
				psel->brp_jobid[0] = '\0';
				rc = disrfst(sock, PBS_MAXSVRJOBID+1, psel->brp_jobid);
				if (rc) {
					(void)free(psel);
					return rc;
				}
				*pselx = psel;
				pselx = &psel->brp_next;
			}
			break;

		case BATCH_REPLY_CHOICE_Status:

			/* have to get count of number of status objects first */

			CLEAR_HEAD(reply->brp_un.brp_status);
			ct = disrui(sock, &rc);
			if (rc) return rc;

			while (ct--) {
				pstsvr = (struct brp_status *)malloc(sizeof(struct brp_status));
				if (pstsvr == 0) return DIS_NOMALLOC;

				CLEAR_LINK(pstsvr->brp_stlink);
				pstsvr->brp_objname[0] = '\0';
				CLEAR_HEAD(pstsvr->brp_attr);

				pstsvr->brp_objtype = disrui(sock, &rc);
				if (rc == 0) {
					rc = disrfst(sock, PBS_MAXSVRJOBID+1,
						pstsvr->brp_objname);
				}
				if (rc) {
					(void)free(pstsvr);
					return rc;
				}
				append_link(&reply->brp_un.brp_status,
					&pstsvr->brp_stlink, pstsvr);
				rc = decode_DIS_svrattrl(sock, &pstsvr->brp_attr);
			}
			break;

		case BATCH_REPLY_CHOICE_Text:

			/* text reply */

		  	reply->brp_un.brp_txt.brp_str = disrcs(sock, &txtlen, &rc);
			reply->brp_un.brp_txt.brp_txtlen = txtlen;
			break;

		case BATCH_REPLY_CHOICE_Locate:

			/* Locate Job Reply */

			rc = disrfst(sock, PBS_MAXDEST+1, reply->brp_un.brp_locate);
			break;

		default:
			return -1;
	}

	return rc;
}
