/* This test driver program encodes a data record and writes the        */
/* encoded result to an output file..                                   */

#include <stdio.h>
#include <stdlib.h>
#include "ACSE-1.h"

#define MAXMSGLEN 1024

static int encodeACSEConnectionResponse (ASN1BEREncodeBuffer& encodeBuffer);

/* These two function declarations are blocked out to avoid a compiler warning,
   but they're here for reference.  */
#if 0
static int encodeACSEReleaseResponse (ASN1BEREncodeBuffer& encodeBuffer);
static int encodeACSEAbort (ASN1BEREncodeBuffer& encodeBuffer);
#endif

int main (int argc, char** argv)
{
   /* Run-time support variables */

   const OSOCTET* msgptr;
   OSOCTET	msgbuf[MAXMSGLEN];
   int		i, len;
   FILE*        fp;
   const char*        filename = "message.dat";
   OSBOOL     trace = TRUE;

   /* Process command line arguments */

   if (argc > 1) {
      for (i = 1; i < argc; i++) {
         if (!strcmp (argv[i], "-v")) trace = TRUE;
         else if (!strcmp (argv[i], "-o")) filename = argv[++i];
         else if (!strcmp (argv[i], "-notrace")) trace = FALSE;
         else {
            printf ("usage: writer [ -v ] [ -o <filename>\n");
            printf ("   -v  verbose mode: print trace info\n");
            printf ("   -o <filename>  write encoded msg to <filename>\n");
            printf ("   -notrace  do not display trace info\n");
            return 0;
         }
      }
   }


      /* Initialize the encoding context */

      ASN1BEREncodeBuffer encodeBuffer (msgbuf, sizeof(msgbuf));

      /* Encode ACSE */
      /* 
         For connectionRequest response call encodeACSEConnectionResponse()
         For releaseConnectionRequest response call encodeACSEReleaseResponse()
         For abort connection call encodeACSEAbort()
      */
      if ((len = encodeACSEConnectionResponse (encodeBuffer)) < 0) return len;
      

      msgptr = encodeBuffer.getMsgPtr();

      if (trace) {
         encodeBuffer.binDump();
      }

      /* Write the encoded message out to the output file */

      /* Note that g++ on Linux suggests the inner parentheses around the
         "assignment used as truth value".  I disagree, but here they are to
         eliminate the warning message.  */
      if ((fp = fopen (filename, "wb"))) {
         fwrite (msgptr, 1, len, fp);
         fclose (fp);
      }
      else {
         printf ("Error opening %s for write access\n", filename);
         return -1;
      }

   return 0;

}

/* Encode ACSE Connection Response 

The ACSE_apdu.aare(response) is transmitted to the CSTA Application,
waitting for a response for an ACSE_apdu.aarq(request). 
*/

static int encodeACSEConnectionResponse (ASN1BEREncodeBuffer& encodeBuffer)
{
   ASN1T_AARE_apdu aare_apdu;
   int len;
  
   /*
   set CSTA 3 OID value, for CSTA 3 communication 
   { iso( 1) identified-organization( 3) icd-ecma( 12)
	standard( 0) csta3( 285) application-context-information( 200) }
   */
   ASN1OBJID csta3oid = { 6, {1, 3, 12, 0, 285, 200 } };
   aare_apdu.aSO_context_name = csta3oid;
   
   aare_apdu.result = Associate_result::accepted;
   aare_apdu.result_source_diagnostic.t = T_Associate_source_diagnostic_acse_service_provider;
   aare_apdu.result_source_diagnostic.u.acse_service_provider
      = Associate_source_diagnostic_acse_service_provider::null_;

   /* All other optional fields are ignored for simplicity */

   /* Encode */
   ASN1T_ACSE_apdu acse_apdu;
   acse_apdu.t = T_ACSE_apdu_aare;
   acse_apdu.u.aare = &aare_apdu;

   ASN1C_ACSE_apdu pdu(encodeBuffer, acse_apdu);

   len = pdu.Encode();

   if (len < 0) {
      printf ("Encode of ACSE pdu failed.\n");
      encodeBuffer.printErrorInfo();
   }

   return len;
}

/* Encode ACSE connection Release Response 

The ACSE_apdu.rlre(response) is transmitted to the CSTA Application,
waitting for a response for an ACSE_apdu.rlrq(request). 

*/

/* This function is blocked out to prevent a compiler warning, but it's here
   for reference.  */

#if 0
static int encodeACSEReleaseResponse (ASN1BEREncodeBuffer& encodeBuffer)
{
   ASN1T_RLRE_apdu rlre_apdu;
   int len;

   rlre_apdu.m.reasonPresent = 1;
   rlre_apdu.reason = Release_request_reason::normal;

   /* All other optional fields are ignored for simplicity. */

   /* Encode */
   ASN1T_ACSE_apdu acse_apdu;
   acse_apdu.t = T_ACSE_apdu_rlre;
   acse_apdu.u.rlre = &rlre_apdu;

   ASN1C_ACSE_apdu pdu(encodeBuffer, acse_apdu);

   len = pdu.Encode();

   if (len < 0) {
      printf ("Encode ACSE PDU failed.\n");
      encodeBuffer.printErrorInfo();
   }

   return len;
}
#endif

/* Encode ACSE connection abort, this is not a Request */

/* This function is blocked out to prevent a compiler warning, but it's here
   for reference.  */

#if 0
static int encodeACSEAbort (ASN1BEREncodeBuffer& encodeBuffer)
{
   ASN1T_ABRT_apdu abrt_apdu;
   int len;

   abrt_apdu.abort_source = ABRT_source::acse_service_user;

   /* All other optional fields are ignored for simplicity. */

   /* Encode */
   ASN1T_ACSE_apdu acse_apdu;
   acse_apdu.t = T_ACSE_apdu_abrt;
   acse_apdu.u.abrt = &abrt_apdu;

   ASN1C_ACSE_apdu pdu(encodeBuffer, acse_apdu);

   len = pdu.Encode();

   if (len < 0) {
      printf ("Encode ACSE PDU failed.\n");
      encodeBuffer.printErrorInfo();
   }

   return len;
}
#endif
